diff options
Diffstat (limited to 'Demo/pdist')
-rw-r--r-- | Demo/pdist/FSProxy.py | 301 | ||||
-rwxr-xr-x | Demo/pdist/RCSProxy.py | 198 | ||||
-rw-r--r-- | Demo/pdist/README | 121 | ||||
-rw-r--r-- | Demo/pdist/client.py | 156 | ||||
-rw-r--r-- | Demo/pdist/cmdfw.py | 142 | ||||
-rw-r--r-- | Demo/pdist/cmptree.py | 213 | ||||
-rw-r--r-- | Demo/pdist/cvslib.py | 359 | ||||
-rw-r--r-- | Demo/pdist/cvslock.py | 279 | ||||
-rw-r--r-- | Demo/pdist/mac.py | 24 | ||||
-rwxr-xr-x | Demo/pdist/makechangelog.py | 109 | ||||
-rwxr-xr-x | Demo/pdist/rcsbump | 33 | ||||
-rw-r--r-- | Demo/pdist/rcsclient.py | 71 | ||||
-rw-r--r-- | Demo/pdist/rcslib.py | 334 | ||||
-rwxr-xr-x | Demo/pdist/rcvs | 8 | ||||
-rwxr-xr-x | Demo/pdist/rcvs.py | 476 | ||||
-rwxr-xr-x | Demo/pdist/rrcs | 8 | ||||
-rwxr-xr-x | Demo/pdist/rrcs.py | 158 | ||||
-rw-r--r-- | Demo/pdist/security.py | 33 | ||||
-rw-r--r-- | Demo/pdist/server.py | 143 | ||||
-rw-r--r-- | Demo/pdist/sumtree.py | 27 |
20 files changed, 0 insertions, 3193 deletions
diff --git a/Demo/pdist/FSProxy.py b/Demo/pdist/FSProxy.py deleted file mode 100644 index 47fa8f9..0000000 --- a/Demo/pdist/FSProxy.py +++ /dev/null @@ -1,301 +0,0 @@ -"""File System Proxy. - -Provide an OS-neutral view on a file system, locally or remotely. -The functionality is geared towards implementing some sort of -rdist-like utility between a Mac and a UNIX system. - -The module defines three classes: - -FSProxyLocal -- used for local access -FSProxyServer -- used on the server side of remote access -FSProxyClient -- 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 -from stat import * -import time -import fnmatch - -maxnamelen = 255 - -skipnames = (os.curdir, os.pardir) - - -class FSProxyLocal: - - def __init__(self): - self._dirstack = [] - self._ignore = ['*.pyc'] + self._readignore() - - def _close(self): - while self._dirstack: - self.back() - - def _readignore(self): - file = self._hide('ignore') - try: - f = open(file) - except IOError: - file = self._hide('synctree.ignorefiles') - try: - f = open(file) - except IOError: - return [] - ignore = [] - while 1: - line = f.readline() - if not line: break - if line[-1] == '\n': line = line[:-1] - ignore.append(line) - f.close() - return ignore - - def _hidden(self, name): - return name[0] == '.' - - def _hide(self, name): - return '.%s' % name - - def visible(self, name): - if len(name) > maxnamelen: return 0 - if name[-1] == '~': return 0 - if name in skipnames: return 0 - if self._hidden(name): return 0 - head, tail = os.path.split(name) - if head or not tail: return 0 - if os.path.islink(name): return 0 - if '\0' in open(name, 'rb').read(512): return 0 - for ign in self._ignore: - if fnmatch.fnmatch(name, ign): return 0 - return 1 - - def check(self, name): - if not self.visible(name): - raise os.error("protected name %s" % repr(name)) - - def checkfile(self, name): - self.check(name) - if not os.path.isfile(name): - raise os.error("not a plain file %s" % repr(name)) - - def pwd(self): - return os.getcwd() - - def cd(self, name): - self.check(name) - save = os.getcwd(), self._ignore - os.chdir(name) - self._dirstack.append(save) - self._ignore = self._ignore + self._readignore() - - def back(self): - if not self._dirstack: - raise os.error("empty directory stack") - dir, ignore = self._dirstack[-1] - os.chdir(dir) - del self._dirstack[-1] - self._ignore = ignore - - def _filter(self, files, pat = None): - if pat: - def keep(name, pat = pat): - return fnmatch.fnmatch(name, pat) - files = list(filter(keep, files)) - files = list(filter(self.visible, files)) - files.sort() - return files - - def list(self, pat = None): - files = os.listdir(os.curdir) - return self._filter(files, pat) - - def listfiles(self, pat = None): - files = os.listdir(os.curdir) - files = list(filter(os.path.isfile, files)) - return self._filter(files, pat) - - def listsubdirs(self, pat = None): - files = os.listdir(os.curdir) - files = list(filter(os.path.isdir, files)) - return self._filter(files, pat) - - def exists(self, name): - return self.visible(name) and os.path.exists(name) - - def isdir(self, name): - return self.visible(name) and os.path.isdir(name) - - def islink(self, name): - return self.visible(name) and os.path.islink(name) - - def isfile(self, name): - return self.visible(name) and os.path.isfile(name) - - def sum(self, name): - self.checkfile(name) - BUFFERSIZE = 1024*8 - f = open(name) - sum = md5.new() - while 1: - buffer = f.read(BUFFERSIZE) - if not buffer: - break - sum.update(buffer) - return sum.digest() - - def size(self, name): - self.checkfile(name) - return os.stat(name)[ST_SIZE] - - def mtime(self, name): - self.checkfile(name) - return time.localtime(os.stat(name)[ST_MTIME]) - - def stat(self, name): - self.checkfile(name) - size = os.stat(name)[ST_SIZE] - mtime = time.localtime(os.stat(name)[ST_MTIME]) - return size, mtime - - def info(self, name): - sum = self.sum(name) - size = os.stat(name)[ST_SIZE] - mtime = time.localtime(os.stat(name)[ST_MTIME]) - return sum, size, mtime - - 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 statlist(self, list = None): - return self._list(self.stat, list) - - def mtimelist(self, list = None): - return self._list(self.mtime, list) - - def sizelist(self, list = None): - return self._list(self.size, list) - - def infolist(self, list = None): - return self._list(self.info, 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 sizedict(self, list = None): - return self.dict(self.size, list) - - def mtimedict(self, list = None): - return self.dict(self.mtime, list) - - def statdict(self, list = None): - return self.dict(self.stat, list) - - def infodict(self, list = None): - return self._dict(self.info, list) - - def read(self, name, offset = 0, length = -1): - self.checkfile(name) - f = open(name) - f.seek(offset) - if length == 0: - data = '' - elif length < 0: - data = f.read() - else: - data = f.read(length) - f.close() - return data - - def create(self, name): - self.check(name) - if os.path.exists(name): - self.checkfile(name) - bname = name + '~' - try: - os.unlink(bname) - except os.error: - pass - os.rename(name, bname) - f = open(name, 'w') - f.close() - - def write(self, name, data, offset = 0): - self.checkfile(name) - f = open(name, 'r+') - f.seek(offset) - f.write(data) - f.close() - - def mkdir(self, name): - self.check(name) - os.mkdir(name, 0o777) - - def rmdir(self, name): - self.check(name) - os.rmdir(name) - - -class FSProxyServer(FSProxyLocal, server.Server): - - def __init__(self, address, verbose = server.VERBOSE): - FSProxyLocal.__init__(self) - server.Server.__init__(self, address, verbose) - - def _close(self): - server.Server._close(self) - FSProxyLocal._close(self) - - def _serve(self): - server.Server._serve(self) - # Retreat into start directory - while self._dirstack: self.back() - - -class FSProxyClient(client.Client): - - def __init__(self, address, verbose = client.VERBOSE): - client.Client.__init__(self, address, verbose) - - -def test(): - import string - import sys - if sys.argv[1:]: - port = string.atoi(sys.argv[1]) - else: - port = 4127 - proxy = FSProxyServer(('', port)) - proxy._serverloop() - - -if __name__ == '__main__': - test() diff --git a/Demo/pdist/RCSProxy.py b/Demo/pdist/RCSProxy.py deleted file mode 100755 index b0a01ad..0000000 --- a/Demo/pdist/RCSProxy.py +++ /dev/null @@ -1,198 +0,0 @@ -#! /usr/bin/env python3 - -"""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 two classes: - -RCSProxyLocal -- used for local access -RCSProxyServer -- used on the server side of remote access - -The corresponding client class, RCSProxyClient, is defined in module -rcsclient. - -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 -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 = list(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, 0o777) - - def rmdir(self, name): - os.rmdir(name) - - -class RCSProxyLocal(rcslib.RCS, DirSupport): - - 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) - self._remove(name) - - 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 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 hasattr(attr, '__call__'): - print(attr(*sys.argv[2:])) - else: - print(repr(attr)) - else: - print("%s: no such attribute" % what) - sys.exit(2) - - -if __name__ == '__main__': - test() diff --git a/Demo/pdist/README b/Demo/pdist/README deleted file mode 100644 index b3fac24..0000000 --- a/Demo/pdist/README +++ /dev/null @@ -1,121 +0,0 @@ -Filesystem, RCS and CVS client and server classes -================================================= - -*** See the security warning at the end of this file! *** - -This directory contains various modules and classes that support -remote file system operations. - -CVS stuff ---------- - -rcvs Script to put in your bin directory -rcvs.py Remote CVS client command line interface - -cvslib.py CVS admin files classes (used by rrcs) -cvslock.py CVS locking algorithms - -RCS stuff ---------- - -rrcs Script to put in your bin directory -rrcs.py Remote RCS client command line interface - -rcsclient.py Return an RCSProxyClient instance - (has reasonable default server/port/directory) - -RCSProxy.py RCS proxy and server classes (on top of rcslib.py) - -rcslib.py Local-only RCS base class (affects stdout & - local work files) - -FSProxy stuff -------------- - -sumtree.py Old demo for FSProxy -cmptree.py First FSProxy client (used to sync from the Mac) -FSProxy.py Filesystem interface classes - -Generic client/server stuff ---------------------------- - -client.py Client class -server.py Server class - -security.py Security mix-in class (not very secure I think) - -Other generic stuff -------------------- - -cmdfw.py CommandFrameWork class - (used by rcvs, should be used by rrcs as well) - - -Client/Server operation ------------------------ - -The Client and Server classes implement a simple-minded RPC protocol, -using Python's pickle module to transfer arguments, return values and -exceptions with the most generality. The Server class is instantiated -with a port number on which it should listen for requests; the Client -class is instantiated with a host name and a port number where it -should connect to. Once a client is connected, a TCP connection is -maintained between client and server. - -The Server class currently handles only one connection at a time; -however it could be rewritten to allow various modes of operations, -using multiple threads or processes or the select() system call as -desired to serve multiple clients simultaneously (when using select(), -still handling one request at a time). This would not require -rewriting of the Client class. It may also be possible to adapt the -code to use UDP instead of TCP, but then both classes will have to be -rewritten (and unless extensive acknowlegements and request serial -numbers are used, the server should handle duplicate requests, so its -semantics should be idempotent -- shrudder). - -Even though the FSProxy and RCSProxy modules define client classes, -the client class is fully generic -- what methods it supports is -determined entirely by the server. The server class, however, must be -derived from. This is generally done as follows: - - from server import Server - from client import Client - - # Define a class that performs the operations locally - class MyClassLocal: - def __init__(self): ... - def _close(self): ... - - # Derive a server class using multiple inheritance - class MyClassServer(MyClassLocal, Server): - def __init__(self, address): - # Must initialize MyClassLocal as well as Server - MyClassLocal.__init__(self) - Server.__init__(self, address) - def _close(self): - Server._close() - MyClassLocal._close() - - # A dummy client class - class MyClassClient(Client): pass - -Note that because MyClassLocal isn't used in the definition of -MyClassClient, it would actually be better to place it in a separate -module so the definition of MyClassLocal isn't executed when we only -instantiate a client. - -The modules client and server should probably be renamed to Client and -Server in order to match the class names. - - -*** Security warning: this version requires that you have a file -$HOME/.python_keyfile at the server and client side containing two -comma- separated numbers. The security system at the moment makes no -guarantees of actuallng being secure -- however it requires that the -key file exists and contains the same numbers at both ends for this to -work. (You can specify an alternative keyfile in $PYTHON_KEYFILE). -Have a look at the Security class in security.py for details; -basically, if the key file contains (x, y), then the security server -class chooses a random number z (the challenge) in the range -10..100000 and the client must be able to produce pow(z, x, y) -(i.e. z**x mod y). diff --git a/Demo/pdist/client.py b/Demo/pdist/client.py deleted file mode 100644 index c9fe369..0000000 --- a/Demo/pdist/client.py +++ /dev/null @@ -1,156 +0,0 @@ -"""RPC Client module.""" - -import sys -import socket -import pickle -import builtins -import os - - -# Default verbosity (0 = silent, 1 = print connections, 2 = print requests too) -VERBOSE = 1 - - -class Client: - - """RPC Client class. No need to derive a class -- it's fully generic.""" - - def __init__(self, address, verbose = VERBOSE): - self._pre_init(address, verbose) - self._post_init() - - def _pre_init(self, address, verbose = VERBOSE): - if type(address) == type(0): - address = ('', address) - self._address = address - self._verbose = verbose - if self._verbose: print("Connecting to %s ..." % repr(address)) - self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - self._socket.connect(address) - if self._verbose: print("Connected.") - self._lastid = 0 # Last id for which a reply has been received - self._nextid = 1 # Id of next request - self._replies = {} # Unprocessed replies - self._rf = self._socket.makefile('r') - self._wf = self._socket.makefile('w') - - def _post_init(self): - self._methods = self._call('.methods') - - def __del__(self): - self._close() - - def _close(self): - if self._rf: self._rf.close() - self._rf = None - if self._wf: self._wf.close() - self._wf = None - if self._socket: self._socket.close() - self._socket = None - - def __getattr__(self, name): - if name in self._methods: - method = _stub(self, name) - setattr(self, name, method) # XXX circular reference - return method - raise AttributeError(name) - - def _setverbose(self, verbose): - self._verbose = verbose - - def _call(self, name, *args): - return self._vcall(name, args) - - def _vcall(self, name, args): - return self._recv(self._vsend(name, args)) - - def _send(self, name, *args): - return self._vsend(name, args) - - def _send_noreply(self, name, *args): - return self._vsend(name, args, 0) - - def _vsend_noreply(self, name, args): - return self._vsend(name, args, 0) - - def _vsend(self, name, args, wantreply = 1): - id = self._nextid - self._nextid = id+1 - if not wantreply: id = -id - request = (name, args, id) - if self._verbose > 1: print("sending request: %s" % repr(request)) - wp = pickle.Pickler(self._wf) - wp.dump(request) - return id - - def _recv(self, id): - exception, value, rid = self._vrecv(id) - if rid != id: - raise RuntimeError("request/reply id mismatch: %d/%d" % (id, rid)) - if exception is None: - return value - x = exception - if hasattr(builtins, exception): - x = getattr(builtins, exception) - elif exception in ('posix.error', 'mac.error'): - x = os.error - if x == exception: - exception = x - raise exception(value) - - def _vrecv(self, id): - self._flush() - if id in self._replies: - if self._verbose > 1: print("retrieving previous reply, id = %d" % id) - reply = self._replies[id] - del self._replies[id] - return reply - aid = abs(id) - while 1: - if self._verbose > 1: print("waiting for reply, id = %d" % id) - rp = pickle.Unpickler(self._rf) - reply = rp.load() - del rp - if self._verbose > 1: print("got reply: %s" % repr(reply)) - rid = reply[2] - arid = abs(rid) - if arid == aid: - if self._verbose > 1: print("got it") - return reply - self._replies[rid] = reply - if arid > aid: - if self._verbose > 1: print("got higher id, assume all ok") - return (None, None, id) - - def _flush(self): - self._wf.flush() - - -from security import Security - - -class SecureClient(Client, Security): - - def __init__(self, *args): - self._pre_init(*args) - Security.__init__(self) - self._wf.flush() - line = self._rf.readline() - challenge = int(line.strip()) - response = self._encode_challenge(challenge) - line = repr(int(response)) - if line[-1] in 'Ll': line = line[:-1] - self._wf.write(line + '\n') - self._wf.flush() - self._post_init() - -class _stub: - - """Helper class for Client -- each instance serves as a method of the client.""" - - def __init__(self, client, name): - self._client = client - self._name = name - - def __call__(self, *args): - return self._client._vcall(self._name, args) diff --git a/Demo/pdist/cmdfw.py b/Demo/pdist/cmdfw.py deleted file mode 100644 index ec854b1..0000000 --- a/Demo/pdist/cmdfw.py +++ /dev/null @@ -1,142 +0,0 @@ -"Framework for command line interfaces like CVS. See class CmdFrameWork." - - -class CommandFrameWork: - - """Framework class for command line interfaces like CVS. - - The general command line structure is - - command [flags] subcommand [subflags] [argument] ... - - There's a class variable GlobalFlags which specifies the - global flags options. Subcommands are defined by defining - methods named do_<subcommand>. Flags for the subcommand are - defined by defining class or instance variables named - flags_<subcommand>. If there's no command, method default() - is called. The __doc__ strings for the do_ methods are used - for the usage message, printed after the general usage message - which is the class variable UsageMessage. The class variable - PostUsageMessage is printed after all the do_ methods' __doc__ - strings. The method's return value can be a suggested exit - status. [XXX Need to rewrite this to clarify it.] - - Common usage is to derive a class, instantiate it, and then call its - run() method; by default this takes its arguments from sys.argv[1:]. - """ - - UsageMessage = \ - "usage: (name)s [flags] subcommand [subflags] [argument] ..." - - PostUsageMessage = None - - GlobalFlags = '' - - def __init__(self): - """Constructor, present for completeness.""" - pass - - def run(self, args = None): - """Process flags, subcommand and options, then run it.""" - import getopt, sys - if args is None: args = sys.argv[1:] - try: - opts, args = getopt.getopt(args, self.GlobalFlags) - except getopt.error as msg: - return self.usage(msg) - self.options(opts) - if not args: - self.ready() - return self.default() - else: - cmd = args[0] - mname = 'do_' + cmd - fname = 'flags_' + cmd - try: - method = getattr(self, mname) - except AttributeError: - return self.usage("command %r unknown" % (cmd,)) - try: - flags = getattr(self, fname) - except AttributeError: - flags = '' - try: - opts, args = getopt.getopt(args[1:], flags) - except getopt.error as msg: - return self.usage( - "subcommand %s: " % cmd + str(msg)) - self.ready() - return method(opts, args) - - def options(self, opts): - """Process the options retrieved by getopt. - Override this if you have any options.""" - if opts: - print("-"*40) - print("Options:") - for o, a in opts: - print('option', o, 'value', repr(a)) - print("-"*40) - - def ready(self): - """Called just before calling the subcommand.""" - pass - - def usage(self, msg = None): - """Print usage message. Return suitable exit code (2).""" - if msg: print(msg) - print(self.UsageMessage % {'name': self.__class__.__name__}) - docstrings = {} - c = self.__class__ - while 1: - for name in dir(c): - if name[:3] == 'do_': - if name in docstrings: - continue - try: - doc = getattr(c, name).__doc__ - except: - doc = None - if doc: - docstrings[name] = doc - if not c.__bases__: - break - c = c.__bases__[0] - if docstrings: - print("where subcommand can be:") - for name in sorted(docstrings.keys()): - print(docstrings[name]) - if self.PostUsageMessage: - print(self.PostUsageMessage) - return 2 - - def default(self): - """Default method, called when no subcommand is given. - You should always override this.""" - print("Nobody expects the Spanish Inquisition!") - - -def test(): - """Test script -- called when this module is run as a script.""" - import sys - class Hello(CommandFrameWork): - def do_hello(self, opts, args): - "hello -- print 'hello world', needs no arguments" - print("Hello, world") - x = Hello() - tests = [ - [], - ['hello'], - ['spam'], - ['-x'], - ['hello', '-x'], - None, - ] - for t in tests: - print('-'*10, t, '-'*10) - sts = x.run(t) - print("Exit status:", repr(sts)) - - -if __name__ == '__main__': - test() diff --git a/Demo/pdist/cmptree.py b/Demo/pdist/cmptree.py deleted file mode 100644 index c1bbf1a..0000000 --- a/Demo/pdist/cmptree.py +++ /dev/null @@ -1,213 +0,0 @@ -"""Compare local and remote dictionaries and transfer differing files -- like rdist.""" - -import sys -from reprlib import repr -import FSProxy -import time -import os - -def raw_input(prompt): - sys.stdout.write(prompt) - sys.stdout.flush() - return sys.stdin.readline() - -def main(): - pwd = os.getcwd() - s = input("chdir [%s] " % pwd) - if s: - os.chdir(s) - pwd = os.getcwd() - host = ask("host", 'voorn.cwi.nl') - port = 4127 - verbose = 1 - mode = '' - print("""\ -Mode should be a string of characters, indicating what to do with differences. -r - read different files to local file system -w - write different files to remote file system -c - create new files, either remote or local -d - delete disappearing files, either remote or local -""") - s = input("mode [%s] " % mode) - if s: mode = s - address = (host, port) - t1 = time.time() - local = FSProxy.FSProxyLocal() - remote = FSProxy.FSProxyClient(address, verbose) - compare(local, remote, mode) - remote._close() - local._close() - t2 = time.time() - dt = t2-t1 - mins, secs = divmod(dt, 60) - print(mins, "minutes and", round(secs), "seconds") - input("[Return to exit] ") - -def ask(prompt, default): - s = input("%s [%s] " % (prompt, default)) - return s or default - -def askint(prompt, default): - s = input("%s [%s] " % (prompt, str(default))) - if s: return string.atoi(s) - return default - -def compare(local, remote, mode): - print() - print("PWD =", repr(os.getcwd())) - sums_id = remote._send('sumlist') - subdirs_id = remote._send('listsubdirs') - remote._flush() - print("calculating local sums ...") - lsumdict = {} - for name, info in local.sumlist(): - lsumdict[name] = info - print("getting remote sums ...") - sums = remote._recv(sums_id) - print("got", len(sums)) - rsumdict = {} - for name, rsum in sums: - rsumdict[name] = rsum - if name not in lsumdict: - print(repr(name), "only remote") - if 'r' in mode and 'c' in mode: - recvfile(local, remote, name) - else: - lsum = lsumdict[name] - if lsum != rsum: - print(repr(name), end=' ') - rmtime = remote.mtime(name) - lmtime = local.mtime(name) - if rmtime > lmtime: - print("remote newer", end=' ') - if 'r' in mode: - recvfile(local, remote, name) - elif lmtime > rmtime: - print("local newer", end=' ') - if 'w' in mode: - sendfile(local, remote, name) - else: - print("same mtime but different sum?!?!", end=' ') - print() - for name in lsumdict.keys(): - if not list(rsumdict.keys()): - print(repr(name), "only locally", end=' ') - fl() - if 'w' in mode and 'c' in mode: - sendfile(local, remote, name) - elif 'r' in mode and 'd' in mode: - os.unlink(name) - print("removed.") - print() - print("gettin subdirs ...") - subdirs = remote._recv(subdirs_id) - common = [] - for name in subdirs: - if local.isdir(name): - print("Common subdirectory", repr(name)) - common.append(name) - else: - print("Remote subdirectory", repr(name), "not found locally") - if 'r' in mode and 'c' in mode: - pr = "Create local subdirectory %s? [y] " % \ - repr(name) - if 'y' in mode: - ok = 'y' - else: - ok = ask(pr, "y") - if ok[:1] in ('y', 'Y'): - local.mkdir(name) - print("Subdirectory %s made" % \ - repr(name)) - common.append(name) - lsubdirs = local.listsubdirs() - for name in lsubdirs: - if name not in subdirs: - print("Local subdirectory", repr(name), "not found remotely") - for name in common: - print("Entering subdirectory", repr(name)) - local.cd(name) - remote.cd(name) - compare(local, remote, mode) - remote.back() - local.back() - -def sendfile(local, remote, name): - try: - remote.create(name) - except (IOError, os.error) as msg: - print("cannot create:", msg) - return - - print("sending ...", end=' ') - fl() - - data = open(name).read() - - t1 = time.time() - - remote._send_noreply('write', name, data) - remote._flush() - - t2 = time.time() - - dt = t2-t1 - print(len(data), "bytes in", round(dt), "seconds", end=' ') - if dt: - print("i.e.", round(len(data)/dt), "bytes/sec", end=' ') - print() - -def recvfile(local, remote, name): - ok = 0 - try: - rv = recvfile_real(local, remote, name) - ok = 1 - return rv - finally: - if not ok: - print("*** recvfile of %r failed, deleting" % (name,)) - local.delete(name) - -def recvfile_real(local, remote, name): - try: - local.create(name) - except (IOError, os.error) as msg: - print("cannot create:", msg) - return - - print("receiving ...", end=' ') - fl() - - f = open(name, 'w') - t1 = time.time() - - length = 4*1024 - offset = 0 - id = remote._send('read', name, offset, length) - remote._flush() - while 1: - newoffset = offset + length - newid = remote._send('read', name, newoffset, length) - data = remote._recv(id) - id = newid - if not data: break - f.seek(offset) - f.write(data) - offset = newoffset - size = f.tell() - - t2 = time.time() - f.close() - - dt = t2-t1 - print(size, "bytes in", round(dt), "seconds", end=' ') - if dt: - print("i.e.", int(size//dt), "bytes/sec", end=' ') - print() - remote._recv(id) # ignored - -def fl(): - sys.stdout.flush() - -if __name__ == '__main__': - main() diff --git a/Demo/pdist/cvslib.py b/Demo/pdist/cvslib.py deleted file mode 100644 index 78e4fbb..0000000 --- a/Demo/pdist/cvslib.py +++ /dev/null @@ -1,359 +0,0 @@ -"""Utilities for CVS administration.""" - -import string -import os -import time -import md5 -import fnmatch - -if not hasattr(time, 'timezone'): - time.timezone = 0 - -class File: - - """Represent a file's status. - - Instance variables: - - file -- the filename (no slashes), None if uninitialized - lseen -- true if the data for the local file is up to date - eseen -- true if the data from the CVS/Entries entry is up to date - (this implies that the entry must be written back) - rseen -- true if the data for the remote file is up to date - proxy -- RCSProxy instance used to contact the server, or None - - Note that lseen and rseen don't necessary mean that a local - or remote file *exists* -- they indicate that we've checked it. - However, eseen means that this instance corresponds to an - entry in the CVS/Entries file. - - If lseen is true: - - lsum -- checksum of the local file, None if no local file - lctime -- ctime of the local file, None if no local file - lmtime -- mtime of the local file, None if no local file - - If eseen is true: - - erev -- revision, None if this is a no revision (not '0') - enew -- true if this is an uncommitted added file - edeleted -- true if this is an uncommitted removed file - ectime -- ctime of last local file corresponding to erev - emtime -- mtime of last local file corresponding to erev - extra -- 5th string from CVS/Entries file - - If rseen is true: - - rrev -- revision of head, None if non-existent - rsum -- checksum of that revision, Non if non-existent - - If eseen and rseen are both true: - - esum -- checksum of revision erev, None if no revision - - Note - """ - - def __init__(self, file = None): - if file and '/' in file: - raise ValueError("no slash allowed in file") - self.file = file - self.lseen = self.eseen = self.rseen = 0 - self.proxy = None - - def __cmp__(self, other): - return cmp(self.file, other.file) - - def getlocal(self): - try: - self.lmtime, self.lctime = os.stat(self.file)[-2:] - except os.error: - self.lmtime = self.lctime = self.lsum = None - else: - self.lsum = md5.new(open(self.file).read()).digest() - self.lseen = 1 - - def getentry(self, line): - words = string.splitfields(line, '/') - if self.file and words[1] != self.file: - raise ValueError("file name mismatch") - self.file = words[1] - self.erev = words[2] - self.edeleted = 0 - self.enew = 0 - self.ectime = self.emtime = None - if self.erev[:1] == '-': - self.edeleted = 1 - self.erev = self.erev[1:] - if self.erev == '0': - self.erev = None - self.enew = 1 - else: - dates = words[3] - self.ectime = unctime(dates[:24]) - self.emtime = unctime(dates[25:]) - self.extra = words[4] - if self.rseen: - self.getesum() - self.eseen = 1 - - def getremote(self, proxy = None): - if proxy: - self.proxy = proxy - try: - self.rrev = self.proxy.head(self.file) - except (os.error, IOError): - self.rrev = None - if self.rrev: - self.rsum = self.proxy.sum(self.file) - else: - self.rsum = None - if self.eseen: - self.getesum() - self.rseen = 1 - - def getesum(self): - if self.erev == self.rrev: - self.esum = self.rsum - elif self.erev: - name = (self.file, self.erev) - self.esum = self.proxy.sum(name) - else: - self.esum = None - - def putentry(self): - """Return a line suitable for inclusion in CVS/Entries. - - The returned line is terminated by a newline. - If no entry should be written for this file, - return "". - """ - if not self.eseen: - return "" - - rev = self.erev or '0' - if self.edeleted: - rev = '-' + rev - if self.enew: - dates = 'Initial ' + self.file - else: - dates = gmctime(self.ectime) + ' ' + \ - gmctime(self.emtime) - return "/%s/%s/%s/%s/\n" % ( - self.file, - rev, - dates, - self.extra) - - def report(self): - print('-'*50) - def r(key, repr=repr, self=self): - try: - value = repr(getattr(self, key)) - except AttributeError: - value = "?" - print("%-15s:" % key, value) - r("file") - if self.lseen: - r("lsum", hexify) - r("lctime", gmctime) - r("lmtime", gmctime) - if self.eseen: - r("erev") - r("enew") - r("edeleted") - r("ectime", gmctime) - r("emtime", gmctime) - if self.rseen: - r("rrev") - r("rsum", hexify) - if self.eseen: - r("esum", hexify) - - -class CVS: - - """Represent the contents of a CVS admin file (and more). - - Class variables: - - FileClass -- the class to be instantiated for entries - (this should be derived from class File above) - IgnoreList -- shell patterns for local files to be ignored - - Instance variables: - - entries -- a dictionary containing File instances keyed by - their file name - proxy -- an RCSProxy instance, or None - """ - - FileClass = File - - IgnoreList = ['.*', '@*', ',*', '*~', '*.o', '*.a', '*.so', '*.pyc'] - - def __init__(self): - self.entries = {} - self.proxy = None - - def setproxy(self, proxy): - if proxy is self.proxy: - return - self.proxy = proxy - for e in list(self.entries.values()): - e.rseen = 0 - - def getentries(self): - """Read the contents of CVS/Entries""" - self.entries = {} - f = self.cvsopen("Entries") - while 1: - line = f.readline() - if not line: break - e = self.FileClass() - e.getentry(line) - self.entries[e.file] = e - f.close() - - def putentries(self): - """Write CVS/Entries back""" - f = self.cvsopen("Entries", 'w') - for e in list(self.values()): - f.write(e.putentry()) - f.close() - - def getlocalfiles(self): - entries_keys = set(self.entries.keys()) - addlist = os.listdir(os.curdir) - for name in addlist: - if not self.ignored(name): - entries_keys.add(name) - for file in sorted(entries_keys): - try: - e = self.entries[file] - except KeyError: - e = self.entries[file] = self.FileClass(file) - e.getlocal() - - def getremotefiles(self, proxy = None): - if proxy: - self.proxy = proxy - if not self.proxy: - raise RuntimeError("no RCS proxy") - addlist = self.proxy.listfiles() - for file in addlist: - try: - e = self.entries[file] - except KeyError: - e = self.entries[file] = self.FileClass(file) - e.getremote(self.proxy) - - def report(self): - for e in list(self.values()): - e.report() - print('-'*50) - - def keys(self): - return sorted(self.entries.keys()) - - def values(self): - def value(key, self=self): - return self.entries[key] - return [value(k) for k in self.keys()] - - def items(self): - def item(key, self=self): - return (key, self.entries[key]) - return [item(k) for k in self.keys()] - - def cvsexists(self, file): - file = os.path.join("CVS", file) - return os.path.exists(file) - - def cvsopen(self, file, mode = 'r'): - file = os.path.join("CVS", file) - if 'r' not in mode: - self.backup(file) - return open(file, mode) - - def backup(self, file): - if os.path.isfile(file): - bfile = file + '~' - try: os.unlink(bfile) - except os.error: pass - os.rename(file, bfile) - - def ignored(self, file): - if os.path.isdir(file): return True - for pat in self.IgnoreList: - if fnmatch.fnmatch(file, pat): return True - return False - - -# hexify and unhexify are useful to print MD5 checksums in hex format - -hexify_format = '%02x' * 16 -def hexify(sum): - "Return a hex representation of a 16-byte string (e.g. an MD5 digest)" - if sum is None: - return "None" - return hexify_format % tuple(map(ord, sum)) - -def unhexify(hexsum): - "Return the original from a hexified string" - if hexsum == "None": - return None - sum = '' - for i in range(0, len(hexsum), 2): - sum = sum + chr(string.atoi(hexsum[i:i+2], 16)) - return sum - - -unctime_monthmap = {} -def unctime(date): - if date == "None": return None - if not unctime_monthmap: - months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', - 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'] - i = 0 - for m in months: - i = i+1 - unctime_monthmap[m] = i - words = string.split(date) # Day Mon DD HH:MM:SS YEAR - year = string.atoi(words[4]) - month = unctime_monthmap[words[1]] - day = string.atoi(words[2]) - [hh, mm, ss] = list(map(string.atoi, string.splitfields(words[3], ':'))) - ss = ss - time.timezone - return time.mktime((year, month, day, hh, mm, ss, 0, 0, 0)) - -def gmctime(t): - if t is None: return "None" - return time.asctime(time.gmtime(t)) - -def test_unctime(): - now = int(time.time()) - t = time.gmtime(now) - at = time.asctime(t) - print('GMT', now, at) - print('timezone', time.timezone) - print('local', time.ctime(now)) - u = unctime(at) - print('unctime()', u) - gu = time.gmtime(u) - print('->', gu) - print(time.asctime(gu)) - -def test(): - x = CVS() - x.getentries() - x.getlocalfiles() -## x.report() - import rcsclient - proxy = rcsclient.openrcsclient() - x.getremotefiles(proxy) - x.report() - - -if __name__ == "__main__": - test() diff --git a/Demo/pdist/cvslock.py b/Demo/pdist/cvslock.py deleted file mode 100644 index ffaa15e..0000000 --- a/Demo/pdist/cvslock.py +++ /dev/null @@ -1,279 +0,0 @@ -"""CVS locking algorithm. - -CVS locking strategy -==================== - -As reverse engineered from the CVS 1.3 sources (file lock.c): - -- Locking is done on a per repository basis (but a process can hold -write locks for multiple directories); all lock files are placed in -the repository and have names beginning with "#cvs.". - -- Before even attempting to lock, a file "#cvs.tfl.<pid>" is created -(and removed again), to test that we can write the repository. [The -algorithm can still be fooled (1) if the repository's mode is changed -while attempting to lock; (2) if this file exists and is writable but -the directory is not.] - -- While creating the actual read/write lock files (which may exist for -a long time), a "meta-lock" is held. The meta-lock is a directory -named "#cvs.lock" in the repository. The meta-lock is also held while -a write lock is held. - -- To set a read lock: - - - acquire the meta-lock - - create the file "#cvs.rfl.<pid>" - - release the meta-lock - -- To set a write lock: - - - acquire the meta-lock - - check that there are no files called "#cvs.rfl.*" - - if there are, release the meta-lock, sleep, try again - - create the file "#cvs.wfl.<pid>" - -- To release a write lock: - - - remove the file "#cvs.wfl.<pid>" - - rmdir the meta-lock - -- To release a read lock: - - - remove the file "#cvs.rfl.<pid>" - - -Additional notes ----------------- - -- A process should read-lock at most one repository at a time. - -- A process may write-lock as many repositories as it wishes (to avoid -deadlocks, I presume it should always lock them top-down in the -directory hierarchy). - -- A process should make sure it removes all its lock files and -directories when it crashes. - -- Limitation: one user id should not be committing files into the same -repository at the same time. - - -Turn this into Python code --------------------------- - -rl = ReadLock(repository, waittime) - -wl = WriteLock(repository, waittime) - -list = MultipleWriteLock([repository1, repository2, ...], waittime) - -""" - - -import os -import time -import stat -import pwd - - -# Default wait time -DELAY = 10 - - -# XXX This should be the same on all Unix versions -EEXIST = 17 - - -# Files used for locking (must match cvs.h in the CVS sources) -CVSLCK = "#cvs.lck" -CVSRFL = "#cvs.rfl." -CVSWFL = "#cvs.wfl." - - -class Error: - - def __init__(self, msg): - self.msg = msg - - def __repr__(self): - return repr(self.msg) - - def __str__(self): - return str(self.msg) - - -class Locked(Error): - pass - - -class Lock: - - def __init__(self, repository = ".", delay = DELAY): - self.repository = repository - self.delay = delay - self.lockdir = None - self.lockfile = None - pid = repr(os.getpid()) - self.cvslck = self.join(CVSLCK) - self.cvsrfl = self.join(CVSRFL + pid) - self.cvswfl = self.join(CVSWFL + pid) - - def __del__(self): - print("__del__") - self.unlock() - - def setlockdir(self): - while 1: - try: - self.lockdir = self.cvslck - os.mkdir(self.cvslck, 0o777) - return - except os.error as msg: - self.lockdir = None - if msg.args[0] == EEXIST: - try: - st = os.stat(self.cvslck) - except os.error: - continue - self.sleep(st) - continue - raise Error("failed to lock %s: %s" % ( - self.repository, msg)) - - def unlock(self): - self.unlockfile() - self.unlockdir() - - def unlockfile(self): - if self.lockfile: - print("unlink", self.lockfile) - try: - os.unlink(self.lockfile) - except os.error: - pass - self.lockfile = None - - def unlockdir(self): - if self.lockdir: - print("rmdir", self.lockdir) - try: - os.rmdir(self.lockdir) - except os.error: - pass - self.lockdir = None - - def sleep(self, st): - sleep(st, self.repository, self.delay) - - def join(self, name): - return os.path.join(self.repository, name) - - -def sleep(st, repository, delay): - if delay <= 0: - raise Locked(st) - uid = st[stat.ST_UID] - try: - pwent = pwd.getpwuid(uid) - user = pwent[0] - except KeyError: - user = "uid %d" % uid - print("[%s]" % time.ctime(time.time())[11:19], end=' ') - print("Waiting for %s's lock in" % user, repository) - time.sleep(delay) - - -class ReadLock(Lock): - - def __init__(self, repository, delay = DELAY): - Lock.__init__(self, repository, delay) - ok = 0 - try: - self.setlockdir() - self.lockfile = self.cvsrfl - fp = open(self.lockfile, 'w') - fp.close() - ok = 1 - finally: - if not ok: - self.unlockfile() - self.unlockdir() - - -class WriteLock(Lock): - - def __init__(self, repository, delay = DELAY): - Lock.__init__(self, repository, delay) - self.setlockdir() - while 1: - uid = self.readers_exist() - if not uid: - break - self.unlockdir() - self.sleep(uid) - self.lockfile = self.cvswfl - fp = open(self.lockfile, 'w') - fp.close() - - def readers_exist(self): - n = len(CVSRFL) - for name in os.listdir(self.repository): - if name[:n] == CVSRFL: - try: - st = os.stat(self.join(name)) - except os.error: - continue - return st - return None - - -def MultipleWriteLock(repositories, delay = DELAY): - while 1: - locks = [] - for r in repositories: - try: - locks.append(WriteLock(r, 0)) - except Locked as instance: - del locks - break - else: - break - sleep(instance.msg, r, delay) - return list - - -def test(): - import sys - if sys.argv[1:]: - repository = sys.argv[1] - else: - repository = "." - rl = None - wl = None - try: - print("attempting write lock ...") - wl = WriteLock(repository) - print("got it.") - wl.unlock() - print("attempting read lock ...") - rl = ReadLock(repository) - print("got it.") - rl.unlock() - finally: - print([1]) - print([2]) - if rl: - rl.unlock() - print([3]) - if wl: - wl.unlock() - print([4]) - rl = None - print([5]) - wl = None - print([6]) - - -if __name__ == '__main__': - test() diff --git a/Demo/pdist/mac.py b/Demo/pdist/mac.py deleted file mode 100644 index beb77ec..0000000 --- a/Demo/pdist/mac.py +++ /dev/null @@ -1,24 +0,0 @@ -import sys -import rcvs - -def raw_input(prompt): - sys.stdout.write(prompt) - sys.stdout.flush() - return sys.stdin.readline() - -def main(): - while 1: - try: - line = input('$ ') - except EOFError: - break - words = line.split() - if not words: - continue - if words[0] != 'rcvs': - words.insert(0, 'rcvs') - sys.argv = words - rcvs.main() - -if __name__ == '__main__': - main() diff --git a/Demo/pdist/makechangelog.py b/Demo/pdist/makechangelog.py deleted file mode 100755 index dd90657..0000000 --- a/Demo/pdist/makechangelog.py +++ /dev/null @@ -1,109 +0,0 @@ -#! /usr/bin/env python3 - -"""Turn a pile of RCS log output into ChangeLog file entries. - -""" - -import sys -import string -import re -import getopt -import time - -def main(): - args = sys.argv[1:] - opts, args = getopt.getopt(args, 'p:') - prefix = '' - for o, a in opts: - if p == '-p': prefix = a - - f = sys.stdin - allrevs = [] - while 1: - file = getnextfile(f) - if not file: break - revs = [] - while 1: - rev = getnextrev(f, file) - if not rev: - break - revs.append(rev) - if revs: - allrevs[len(allrevs):] = revs - allrevs.sort() - allrevs.reverse() - for rev in allrevs: - formatrev(rev, prefix) - -parsedateprog = re.compile( - '^date: ([0-9]+)/([0-9]+)/([0-9]+) ' + - '([0-9]+):([0-9]+):([0-9]+); author: ([^ ;]+)') - -authormap = { - 'guido': 'Guido van Rossum <guido@cnri.reston.va.us>', - 'jack': 'Jack Jansen <jack@cwi.nl>', - 'sjoerd': 'Sjoerd Mullender <sjoerd@cwi.nl>', - } - -def formatrev(rev, prefix): - dateline, file, revline, log = rev - if parsedateprog.match(dateline) >= 0: - fields = parsedateprog.group(1, 2, 3, 4, 5, 6) - author = parsedateprog.group(7) - if author in authormap: author = authormap[author] - tfields = list(map(string.atoi, fields)) + [0, 0, 0] - tfields[5] = tfields[5] - time.timezone - t = time.mktime(tuple(tfields)) - print(time.ctime(t), '', author) - words = string.split(log) - words[:0] = ['*', prefix + file + ':'] - maxcol = 72-8 - col = maxcol - for word in words: - if col > 0 and col + len(word) >= maxcol: - print() - print('\t' + word, end=' ') - col = -1 - else: - print(word, end=' ') - col = col + 1 + len(word) - print() - print() - -startprog = re.compile("^Working file: (.*)$") - -def getnextfile(f): - while 1: - line = f.readline() - if not line: return None - if startprog.match(line) >= 0: - file = startprog.group(1) - # Skip until first revision - while 1: - line = f.readline() - if not line: return None - if line[:10] == '='*10: return None - if line[:10] == '-'*10: break -## print "Skipped", line, - return file -## else: -## print "Ignored", line, - -def getnextrev(f, file): - # This is called when we are positioned just after a '---' separator - revline = f.readline() - dateline = f.readline() - log = '' - while 1: - line = f.readline() - if not line: break - if line[:10] == '='*10: - # Ignore the *last* log entry for each file since it - # is the revision since which we are logging. - return None - if line[:10] == '-'*10: break - log = log + line - return dateline, file, revline, log - -if __name__ == '__main__': - main() diff --git a/Demo/pdist/rcsbump b/Demo/pdist/rcsbump deleted file mode 100755 index 4fa078e..0000000 --- a/Demo/pdist/rcsbump +++ /dev/null @@ -1,33 +0,0 @@ -#!/usr/bin/env python -# -*- python -*- -# -# guido's version, from rcsbump,v 1.2 1995/06/22 21:27:27 bwarsaw Exp -# -# Python script for bumping up an RCS major revision number. - -import sys -import re -import rcslib -import string - -WITHLOCK = 1 -majorrev_re = re.compile('^[0-9]+') - -dir = rcslib.RCS() - -if sys.argv[1:]: - files = sys.argv[1:] -else: - files = dir.listfiles() - -for file in files: - # get the major revnumber of the file - headbranch = dir.info(file)['head'] - majorrev_re.match(headbranch) - majorrev = string.atoi(majorrev_re.group(0)) + 1 - - if not dir.islocked(file): - dir.checkout(file, WITHLOCK) - - msg = "Bumping major revision number (to %d)" % majorrev - dir.checkin((file, "%s.0" % majorrev), msg, "-f") diff --git a/Demo/pdist/rcsclient.py b/Demo/pdist/rcsclient.py deleted file mode 100644 index d8cb004..0000000 --- a/Demo/pdist/rcsclient.py +++ /dev/null @@ -1,71 +0,0 @@ -"""Customize this file to change the default client etc. - -(In general, it is probably be better to make local operation the -default and to require something like an RCSSERVER environment -variable to enable remote operation.) - -""" - -import string -import os - -# These defaults don't belong here -- they should be taken from the -# environment or from a hidden file in the current directory - -HOST = 'voorn.cwi.nl' -PORT = 4127 -VERBOSE = 1 -LOCAL = 0 - -import client - - -class RCSProxyClient(client.SecureClient): - - def __init__(self, address, verbose = client.VERBOSE): - client.SecureClient.__init__(self, address, verbose) - - -def openrcsclient(opts = []): - "open an RCSProxy client based on a list of options returned by getopt" - import RCSProxy - host = HOST - port = PORT - verbose = VERBOSE - local = LOCAL - directory = None - for o, a in opts: - if o == '-h': - host = a - if ':' in host: - i = string.find(host, ':') - host, p = host[:i], host[i+1:] - if p: - port = string.atoi(p) - if o == '-p': - port = string.atoi(a) - if o == '-d': - directory = a - if o == '-v': - verbose = verbose + 1 - if o == '-q': - verbose = 0 - if o == '-L': - local = 1 - if local: - import RCSProxy - x = RCSProxy.RCSProxyLocal() - else: - address = (host, port) - x = RCSProxyClient(address, verbose) - if not directory: - try: - directory = open(os.path.join("CVS", "Repository")).readline() - except IOError: - pass - else: - if directory[-1] == '\n': - directory = directory[:-1] - if directory: - x.cd(directory) - return x diff --git a/Demo/pdist/rcslib.py b/Demo/pdist/rcslib.py deleted file mode 100644 index 9690f3b..0000000 --- a/Demo/pdist/rcslib.py +++ /dev/null @@ -1,334 +0,0 @@ -"""RCS interface module. - -Defines the class RCS, which represents a directory with rcs version -files and (possibly) corresponding work files. - -""" - - -import fnmatch -import os -import re -import string -import tempfile - - -class RCS: - - """RCS interface class (local filesystem version). - - An instance of this class represents a directory with rcs version - files and (possible) corresponding work files. - - Methods provide access to most rcs operations such as - checkin/checkout, access to the rcs metadata (revisions, logs, - branches etc.) as well as some filesystem operations such as - listing all rcs version files. - - XXX BUGS / PROBLEMS - - - The instance always represents the current directory so it's not - very useful to have more than one instance around simultaneously - - """ - - # Characters allowed in work file names - okchars = string.ascii_letters + string.digits + '-_=+' - - def __init__(self): - """Constructor.""" - pass - - def __del__(self): - """Destructor.""" - pass - - # --- Informational methods about a single file/revision --- - - def log(self, name_rev, otherflags = ''): - """Return the full log text for NAME_REV as a string. - - Optional OTHERFLAGS are passed to rlog. - - """ - f = self._open(name_rev, 'rlog ' + otherflags) - data = f.read() - status = self._closepipe(f) - if status: - data = data + "%s: %s" % status - elif data[-1] == '\n': - data = data[:-1] - return data - - def head(self, name_rev): - """Return the head revision for NAME_REV""" - dict = self.info(name_rev) - return dict['head'] - - def info(self, name_rev): - """Return a dictionary of info (from rlog -h) for NAME_REV - - The dictionary's keys are the keywords that rlog prints - (e.g. 'head' and its values are the corresponding data - (e.g. '1.3'). - - XXX symbolic names and locks are not returned - - """ - f = self._open(name_rev, 'rlog -h') - dict = {} - while 1: - line = f.readline() - if not line: break - if line[0] == '\t': - # XXX could be a lock or symbolic name - # Anything else? - continue - i = string.find(line, ':') - if i > 0: - key, value = line[:i], string.strip(line[i+1:]) - dict[key] = value - status = self._closepipe(f) - if status: - raise IOError(status) - return dict - - # --- Methods that change files --- - - def lock(self, name_rev): - """Set an rcs lock on NAME_REV.""" - name, rev = self.checkfile(name_rev) - cmd = "rcs -l%s %s" % (rev, name) - return self._system(cmd) - - def unlock(self, name_rev): - """Clear an rcs lock on NAME_REV.""" - name, rev = self.checkfile(name_rev) - cmd = "rcs -u%s %s" % (rev, name) - return self._system(cmd) - - def checkout(self, name_rev, withlock=0, otherflags=""): - """Check out NAME_REV to its work file. - - If optional WITHLOCK is set, check out locked, else unlocked. - - The optional OTHERFLAGS is passed to co without - interpretation. - - Any output from co goes to directly to stdout. - - """ - name, rev = self.checkfile(name_rev) - if withlock: lockflag = "-l" - else: lockflag = "-u" - cmd = 'co %s%s %s %s' % (lockflag, rev, otherflags, name) - return self._system(cmd) - - def checkin(self, name_rev, message=None, otherflags=""): - """Check in NAME_REV from its work file. - - The optional MESSAGE argument becomes the checkin message - (default "<none>" if None); or the file description if this is - a new file. - - The optional OTHERFLAGS argument is passed to ci without - interpretation. - - Any output from ci goes to directly to stdout. - - """ - name, rev = self._unmangle(name_rev) - new = not self.isvalid(name) - if not message: message = "<none>" - if message and message[-1] != '\n': - message = message + '\n' - lockflag = "-u" - if new: - f = tempfile.NamedTemporaryFile() - f.write(message) - f.flush() - cmd = 'ci %s%s -t%s %s %s' % \ - (lockflag, rev, f.name, otherflags, name) - else: - message = re.sub(r'([\"$`])', r'\\\1', message) - cmd = 'ci %s%s -m"%s" %s %s' % \ - (lockflag, rev, message, otherflags, name) - return self._system(cmd) - - # --- Exported support methods --- - - def listfiles(self, pat = None): - """Return a list of all version files matching optional PATTERN.""" - files = os.listdir(os.curdir) - files = list(filter(self._isrcs, files)) - if os.path.isdir('RCS'): - files2 = os.listdir('RCS') - files2 = list(filter(self._isrcs, files2)) - files = files + files2 - files = list(map(self.realname, files)) - return self._filter(files, pat) - - def isvalid(self, name): - """Test whether NAME has a version file associated.""" - namev = self.rcsname(name) - return (os.path.isfile(namev) or - os.path.isfile(os.path.join('RCS', namev))) - - def rcsname(self, name): - """Return the pathname of the version file for NAME. - - The argument can be a work file name or a version file name. - If the version file does not exist, the name of the version - file that would be created by "ci" is returned. - - """ - if self._isrcs(name): namev = name - else: namev = name + ',v' - if os.path.isfile(namev): return namev - namev = os.path.join('RCS', os.path.basename(namev)) - if os.path.isfile(namev): return namev - if os.path.isdir('RCS'): - return os.path.join('RCS', namev) - else: - return namev - - def realname(self, namev): - """Return the pathname of the work file for NAME. - - The argument can be a work file name or a version file name. - If the work file does not exist, the name of the work file - that would be created by "co" is returned. - - """ - if self._isrcs(namev): name = namev[:-2] - else: name = namev - if os.path.isfile(name): return name - name = os.path.basename(name) - return name - - def islocked(self, name_rev): - """Test whether FILE (which must have a version file) is locked. - - XXX This does not tell you which revision number is locked and - ignores any revision you may pass in (by virtue of using rlog - -L -R). - - """ - f = self._open(name_rev, 'rlog -L -R') - line = f.readline() - status = self._closepipe(f) - if status: - raise IOError(status) - if not line: return None - if line[-1] == '\n': - line = line[:-1] - return self.realname(name_rev) == self.realname(line) - - def checkfile(self, name_rev): - """Normalize NAME_REV into a (NAME, REV) tuple. - - Raise an exception if there is no corresponding version file. - - """ - name, rev = self._unmangle(name_rev) - if not self.isvalid(name): - raise os.error('not an rcs file %r' % (name,)) - return name, rev - - # --- Internal methods --- - - def _open(self, name_rev, cmd = 'co -p', rflag = '-r'): - """INTERNAL: open a read pipe to NAME_REV using optional COMMAND. - - Optional FLAG is used to indicate the revision (default -r). - - Default COMMAND is "co -p". - - Return a file object connected by a pipe to the command's - output. - - """ - name, rev = self.checkfile(name_rev) - namev = self.rcsname(name) - if rev: - cmd = cmd + ' ' + rflag + rev - return os.popen("%s %r" % (cmd, namev)) - - def _unmangle(self, name_rev): - """INTERNAL: Normalize NAME_REV argument to (NAME, REV) tuple. - - Raise an exception if NAME contains invalid characters. - - A NAME_REV argument is either NAME string (implying REV='') or - a tuple of the form (NAME, REV). - - """ - if type(name_rev) == type(''): - name_rev = name, rev = name_rev, '' - else: - name, rev = name_rev - for c in rev: - if c not in self.okchars: - raise ValueError("bad char in rev") - return name_rev - - def _closepipe(self, f): - """INTERNAL: Close PIPE and print its exit status if nonzero.""" - sts = f.close() - if not sts: return None - detail, reason = divmod(sts, 256) - if reason == 0: return 'exit', detail # Exit status - signal = reason&0x7F - if signal == 0x7F: - code = 'stopped' - signal = detail - else: - code = 'killed' - if reason&0x80: - code = code + '(coredump)' - return code, signal - - def _system(self, cmd): - """INTERNAL: run COMMAND in a subshell. - - Standard input for the command is taken from /dev/null. - - Raise IOError when the exit status is not zero. - - Return whatever the calling method should return; normally - None. - - A derived class may override this method and redefine it to - capture stdout/stderr of the command and return it. - - """ - cmd = cmd + " </dev/null" - sts = os.system(cmd) - if sts: raise IOError("command exit status %d" % sts) - - def _filter(self, files, pat = None): - """INTERNAL: Return a sorted copy of the given list of FILES. - - If a second PATTERN argument is given, only files matching it - are kept. No check for valid filenames is made. - - """ - if pat: - def keep(name, pat = pat): - return fnmatch.fnmatch(name, pat) - files = list(filter(keep, files)) - else: - files = files[:] - files.sort() - return files - - def _remove(self, fn): - """INTERNAL: remove FILE without complaints.""" - try: - os.unlink(fn) - except os.error: - pass - - def _isrcs(self, name): - """INTERNAL: Test whether NAME ends in ',v'.""" - return name[-2:] == ',v' diff --git a/Demo/pdist/rcvs b/Demo/pdist/rcvs deleted file mode 100755 index f82a27a..0000000 --- a/Demo/pdist/rcvs +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env python - -import addpack -addpack.addpack('/home/guido/src/python/Demo/pdist') - -import rcvs - -rcvs.main() diff --git a/Demo/pdist/rcvs.py b/Demo/pdist/rcvs.py deleted file mode 100755 index ff178b7..0000000 --- a/Demo/pdist/rcvs.py +++ /dev/null @@ -1,476 +0,0 @@ -#! /usr/bin/env python3 - -"""Remote CVS -- command line interface""" - -# XXX To do: -# -# Bugs: -# - if the remote file is deleted, "rcvs update" will fail -# -# Functionality: -# - cvs rm -# - descend into directories (alraedy done for update) -# - conflict resolution -# - other relevant commands? -# - branches -# -# - Finesses: -# - retain file mode's x bits -# - complain when "nothing known about filename" -# - edit log message the way CVS lets you edit it -# - cvs diff -rREVA -rREVB -# - send mail the way CVS sends it -# -# Performance: -# - cache remote checksums (for every revision ever seen!) -# - translate symbolic revisions to numeric revisions -# -# Reliability: -# - remote locking -# -# Security: -# - Authenticated RPC? - - -from cvslib import CVS, File -import md5 -import os -import sys -from cmdfw import CommandFrameWork - - -DEF_LOCAL = 1 # Default -l - - -class MyFile(File): - - def action(self): - """Return a code indicating the update status of this file. - - The possible return values are: - - '=' -- everything's fine - '0' -- file doesn't exist anywhere - '?' -- exists locally only - 'A' -- new locally - 'R' -- deleted locally - 'U' -- changed remotely, no changes locally - (includes new remotely or deleted remotely) - 'M' -- changed locally, no changes remotely - 'C' -- conflict: changed locally as well as remotely - (includes cases where the file has been added - or removed locally and remotely) - 'D' -- deleted remotely - 'N' -- new remotely - 'r' -- get rid of entry - 'c' -- create entry - 'u' -- update entry - - (and probably others :-) - """ - if not self.lseen: - self.getlocal() - if not self.rseen: - self.getremote() - if not self.eseen: - if not self.lsum: - if not self.rsum: return '0' # Never heard of - else: - return 'N' # New remotely - else: # self.lsum - if not self.rsum: return '?' # Local only - # Local and remote, but no entry - if self.lsum == self.rsum: - return 'c' # Restore entry only - else: return 'C' # Real conflict - else: # self.eseen - if not self.lsum: - if self.edeleted: - if self.rsum: return 'R' # Removed - else: return 'r' # Get rid of entry - else: # not self.edeleted - if self.rsum: - print("warning:", end=' ') - print(self.file, end=' ') - print("was lost") - return 'U' - else: return 'r' # Get rid of entry - else: # self.lsum - if not self.rsum: - if self.enew: return 'A' # New locally - else: return 'D' # Deleted remotely - else: # self.rsum - if self.enew: - if self.lsum == self.rsum: - return 'u' - else: - return 'C' - if self.lsum == self.esum: - if self.esum == self.rsum: - return '=' - else: - return 'U' - elif self.esum == self.rsum: - return 'M' - elif self.lsum == self.rsum: - return 'u' - else: - return 'C' - - def update(self): - code = self.action() - if code == '=': return - print(code, self.file) - if code in ('U', 'N'): - self.get() - elif code == 'C': - print("%s: conflict resolution not yet implemented" % \ - self.file) - elif code == 'D': - remove(self.file) - self.eseen = 0 - elif code == 'r': - self.eseen = 0 - elif code in ('c', 'u'): - self.eseen = 1 - self.erev = self.rrev - self.enew = 0 - self.edeleted = 0 - self.esum = self.rsum - self.emtime, self.ectime = os.stat(self.file)[-2:] - self.extra = '' - - def commit(self, message = ""): - code = self.action() - if code in ('A', 'M'): - self.put(message) - return 1 - elif code == 'R': - print("%s: committing removes not yet implemented" % \ - self.file) - elif code == 'C': - print("%s: conflict resolution not yet implemented" % \ - self.file) - - def diff(self, opts = []): - self.action() # To update lseen, rseen - flags = '' - rev = self.rrev - # XXX should support two rev options too! - for o, a in opts: - if o == '-r': - rev = a - else: - flags = flags + ' ' + o + a - if rev == self.rrev and self.lsum == self.rsum: - return - flags = flags[1:] - fn = self.file - data = self.proxy.get((fn, rev)) - sum = md5.new(data).digest() - if self.lsum == sum: - return - import tempfile - tf = tempfile.NamedTemporaryFile() - tf.write(data) - tf.flush() - print('diff %s -r%s %s' % (flags, rev, fn)) - sts = os.system('diff %s %s %s' % (flags, tf.name, fn)) - if sts: - print('='*70) - - def commitcheck(self): - return self.action() != 'C' - - def put(self, message = ""): - print("Checking in", self.file, "...") - data = open(self.file).read() - if not self.enew: - self.proxy.lock(self.file) - messages = self.proxy.put(self.file, data, message) - if messages: - print(messages) - self.setentry(self.proxy.head(self.file), self.lsum) - - def get(self): - data = self.proxy.get(self.file) - f = open(self.file, 'w') - f.write(data) - f.close() - self.setentry(self.rrev, self.rsum) - - def log(self, otherflags): - print(self.proxy.log(self.file, otherflags)) - - def add(self): - self.eseen = 0 # While we're hacking... - self.esum = self.lsum - self.emtime, self.ectime = 0, 0 - self.erev = '' - self.enew = 1 - self.edeleted = 0 - self.eseen = 1 # Done - self.extra = '' - - def setentry(self, erev, esum): - self.eseen = 0 # While we're hacking... - self.esum = esum - self.emtime, self.ectime = os.stat(self.file)[-2:] - self.erev = erev - self.enew = 0 - self.edeleted = 0 - self.eseen = 1 # Done - self.extra = '' - - -SENDMAIL = "/usr/lib/sendmail -t" -MAILFORM = """To: %s -Subject: CVS changes: %s - -...Message from rcvs... - -Committed files: - %s - -Log message: - %s -""" - - -class RCVS(CVS): - - FileClass = MyFile - - def __init__(self): - CVS.__init__(self) - - def update(self, files): - for e in self.whichentries(files, 1): - e.update() - - def commit(self, files, message = ""): - list = self.whichentries(files) - if not list: return - ok = 1 - for e in list: - if not e.commitcheck(): - ok = 0 - if not ok: - print("correct above errors first") - return - if not message: - message = input("One-liner: ") - committed = [] - for e in list: - if e.commit(message): - committed.append(e.file) - self.mailinfo(committed, message) - - def mailinfo(self, files, message = ""): - towhom = "sjoerd@cwi.nl, jack@cwi.nl" # XXX - mailtext = MAILFORM % (towhom, ' '.join(files), - ' '.join(files), message) - print('-'*70) - print(mailtext) - print('-'*70) - ok = input("OK to mail to %s? " % towhom) - if ok.lower().strip() in ('y', 'ye', 'yes'): - p = os.popen(SENDMAIL, "w") - p.write(mailtext) - sts = p.close() - if sts: - print("Sendmail exit status %s" % str(sts)) - else: - print("Mail sent.") - else: - print("No mail sent.") - - def report(self, files): - for e in self.whichentries(files): - e.report() - - def diff(self, files, opts): - for e in self.whichentries(files): - e.diff(opts) - - def add(self, files): - if not files: - raise RuntimeError("'cvs add' needs at least one file") - list = [] - for e in self.whichentries(files, 1): - e.add() - - def rm(self, files): - if not files: - raise RuntimeError("'cvs rm' needs at least one file") - raise RuntimeError("'cvs rm' not yet imlemented") - - def log(self, files, opts): - flags = '' - for o, a in opts: - flags = flags + ' ' + o + a - for e in self.whichentries(files): - e.log(flags) - - def whichentries(self, files, localfilestoo = 0): - if files: - list = [] - for file in files: - if file in self.entries: - e = self.entries[file] - else: - e = self.FileClass(file) - self.entries[file] = e - list.append(e) - else: - list = list(self.entries.values()) - for file in self.proxy.listfiles(): - if file in self.entries: - continue - e = self.FileClass(file) - self.entries[file] = e - list.append(e) - if localfilestoo: - for file in os.listdir(os.curdir): - if file not in self.entries \ - and not self.ignored(file): - e = self.FileClass(file) - self.entries[file] = e - list.append(e) - list.sort() - if self.proxy: - for e in list: - if e.proxy is None: - e.proxy = self.proxy - return list - - -class rcvs(CommandFrameWork): - - GlobalFlags = 'd:h:p:qvL' - UsageMessage = \ -"usage: rcvs [-d directory] [-h host] [-p port] [-q] [-v] [subcommand arg ...]" - PostUsageMessage = \ - "If no subcommand is given, the status of all files is listed" - - def __init__(self): - """Constructor.""" - CommandFrameWork.__init__(self) - self.proxy = None - self.cvs = RCVS() - - def close(self): - if self.proxy: - self.proxy._close() - self.proxy = None - - def recurse(self): - self.close() - names = os.listdir(os.curdir) - for name in names: - if name == os.curdir or name == os.pardir: - continue - if name == "CVS": - continue - if not os.path.isdir(name): - continue - if os.path.islink(name): - continue - print("--- entering subdirectory", name, "---") - os.chdir(name) - try: - if os.path.isdir("CVS"): - self.__class__().run() - else: - self.recurse() - finally: - os.chdir(os.pardir) - print("--- left subdirectory", name, "---") - - def options(self, opts): - self.opts = opts - - def ready(self): - import rcsclient - self.proxy = rcsclient.openrcsclient(self.opts) - self.cvs.setproxy(self.proxy) - self.cvs.getentries() - - def default(self): - self.cvs.report([]) - - def do_report(self, opts, files): - self.cvs.report(files) - - def do_update(self, opts, files): - """update [-l] [-R] [file] ...""" - local = DEF_LOCAL - for o, a in opts: - if o == '-l': local = 1 - if o == '-R': local = 0 - self.cvs.update(files) - self.cvs.putentries() - if not local and not files: - self.recurse() - flags_update = '-lR' - do_up = do_update - flags_up = flags_update - - def do_commit(self, opts, files): - """commit [-m message] [file] ...""" - message = "" - for o, a in opts: - if o == '-m': message = a - self.cvs.commit(files, message) - self.cvs.putentries() - flags_commit = 'm:' - do_com = do_commit - flags_com = flags_commit - - def do_diff(self, opts, files): - """diff [difflags] [file] ...""" - self.cvs.diff(files, opts) - flags_diff = 'cbitwcefhnlr:sD:S:' - do_dif = do_diff - flags_dif = flags_diff - - def do_add(self, opts, files): - """add file ...""" - if not files: - print("'rcvs add' requires at least one file") - return - self.cvs.add(files) - self.cvs.putentries() - - def do_remove(self, opts, files): - """remove file ...""" - if not files: - print("'rcvs remove' requires at least one file") - return - self.cvs.remove(files) - self.cvs.putentries() - do_rm = do_remove - - def do_log(self, opts, files): - """log [rlog-options] [file] ...""" - self.cvs.log(files, opts) - flags_log = 'bhLNRtd:s:V:r:' - - -def remove(fn): - try: - os.unlink(fn) - except os.error: - pass - - -def main(): - r = rcvs() - try: - r.run() - finally: - r.close() - - -if __name__ == "__main__": - main() diff --git a/Demo/pdist/rrcs b/Demo/pdist/rrcs deleted file mode 100755 index 31fc2c5..0000000 --- a/Demo/pdist/rrcs +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env python - -import addpack -addpack.addpack('/home/guido/src/python/Demo/pdist') - -import rrcs - -rrcs.main() diff --git a/Demo/pdist/rrcs.py b/Demo/pdist/rrcs.py deleted file mode 100755 index 9e246b8..0000000 --- a/Demo/pdist/rrcs.py +++ /dev/null @@ -1,158 +0,0 @@ -#! /usr/bin/env python3 - -"Remote RCS -- command line interface" - -import sys -import os -import getopt -import string -import md5 -import tempfile -from rcsclient import openrcsclient - -def main(): - sys.stdout = sys.stderr - try: - opts, rest = getopt.getopt(sys.argv[1:], 'h:p:d:qvL') - if not rest: - cmd = 'head' - else: - cmd, rest = rest[0], rest[1:] - if cmd not in commands: - raise getopt.error("unknown command") - coptset, func = commands[cmd] - copts, files = getopt.getopt(rest, coptset) - except getopt.error as msg: - print(msg) - print("usage: rrcs [options] command [options] [file] ...") - print("where command can be:") - print(" ci|put # checkin the given files") - print(" co|get # checkout") - print(" info # print header info") - print(" head # print revision of head branch") - print(" list # list filename if valid") - print(" log # print full log") - print(" diff # diff rcs file and work file") - print("if no files are given, all remote rcs files are assumed") - sys.exit(2) - x = openrcsclient(opts) - if not files: - files = x.listfiles() - for fn in files: - try: - func(x, copts, fn) - except (IOError, os.error) as msg: - print("%s: %s" % (fn, msg)) - -def checkin(x, copts, fn): - f = open(fn) - data = f.read() - f.close() - new = not x.isvalid(fn) - if not new and same(x, copts, fn, data): - print("%s: unchanged since last checkin" % fn) - return - print("Checking in", fn, "...") - message = asklogmessage(new) - messages = x.put(fn, data, message) - if messages: - print(messages) - -def checkout(x, copts, fn): - data = x.get(fn) - f = open(fn, 'w') - f.write(data) - f.close() - -def lock(x, copts, fn): - x.lock(fn) - -def unlock(x, copts, fn): - x.unlock(fn) - -def info(x, copts, fn): - info_dict = x.info(fn) - for key in sorted(info_dict.keys()): - print(key + ':', info_dict[key]) - print('='*70) - -def head(x, copts, fn): - head = x.head(fn) - print(fn, head) - -def list(x, copts, fn): - if x.isvalid(fn): - print(fn) - -def log(x, copts, fn): - flags = '' - for o, a in copts: - flags = flags + ' ' + o + a - flags = flags[1:] - messages = x.log(fn, flags) - print(messages) - -def diff(x, copts, fn): - if same(x, copts, fn): - return - flags = '' - for o, a in copts: - flags = flags + ' ' + o + a - flags = flags[1:] - data = x.get(fn) - tf = tempfile.NamedTemporaryFile() - tf.write(data) - tf.flush() - print('diff %s -r%s %s' % (flags, x.head(fn), fn)) - sts = os.system('diff %s %s %s' % (flags, tf.name, fn)) - if sts: - print('='*70) - -def same(x, copts, fn, data = None): - if data is None: - f = open(fn) - data = f.read() - f.close() - lsum = md5.new(data).digest() - rsum = x.sum(fn) - return lsum == rsum - -def asklogmessage(new): - if new: - print("enter description,", end=' ') - else: - print("enter log message,", end=' ') - print("terminate with single '.' or end of file:") - if new: - print("NOTE: This is NOT the log message!") - message = "" - while 1: - sys.stderr.write(">> ") - sys.stderr.flush() - line = sys.stdin.readline() - if not line or line == '.\n': break - message = message + line - return message - -def remove(fn): - try: - os.unlink(fn) - except os.error: - pass - -commands = { - 'ci': ('', checkin), - 'put': ('', checkin), - 'co': ('', checkout), - 'get': ('', checkout), - 'info': ('', info), - 'head': ('', head), - 'list': ('', list), - 'lock': ('', lock), - 'unlock': ('', unlock), - 'log': ('bhLRtd:l:r:s:w:V:', log), - 'diff': ('c', diff), - } - -if __name__ == '__main__': - main() diff --git a/Demo/pdist/security.py b/Demo/pdist/security.py deleted file mode 100644 index ffdbe2d..0000000 --- a/Demo/pdist/security.py +++ /dev/null @@ -1,33 +0,0 @@ -class Security: - - def __init__(self): - import os - env = os.environ - if 'PYTHON_KEYFILE' in env: - keyfile = env['PYTHON_KEYFILE'] - else: - keyfile = '.python_keyfile' - if 'HOME' in env: - keyfile = os.path.join(env['HOME'], keyfile) - if not os.path.exists(keyfile): - import sys - for dir in sys.path: - kf = os.path.join(dir, keyfile) - if os.path.exists(kf): - keyfile = kf - break - try: - self._key = eval(open(keyfile).readline()) - except IOError: - raise IOError("python keyfile %s: cannot open" % keyfile) - - def _generate_challenge(self): - import random - return random.randint(100, 100000) - - def _compare_challenge_response(self, challenge, response): - return self._encode_challenge(challenge) == response - - def _encode_challenge(self, challenge): - p, m = self._key - return pow(int(challenge), p, m) diff --git a/Demo/pdist/server.py b/Demo/pdist/server.py deleted file mode 100644 index b3943ff..0000000 --- a/Demo/pdist/server.py +++ /dev/null @@ -1,143 +0,0 @@ -"""RPC Server module.""" - -import sys -import socket -import pickle -from fnmatch import fnmatch -from reprlib import repr - - -# Default verbosity (0 = silent, 1 = print connections, 2 = print requests too) -VERBOSE = 1 - - -class Server: - - """RPC Server class. Derive a class to implement a particular service.""" - - def __init__(self, address, verbose = VERBOSE): - if type(address) == type(0): - address = ('', address) - self._address = address - self._verbose = verbose - self._socket = None - self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - self._socket.bind(address) - self._socket.listen(1) - self._listening = 1 - - def _setverbose(self, verbose): - self._verbose = verbose - - def __del__(self): - self._close() - - def _close(self): - self._listening = 0 - if self._socket: - self._socket.close() - self._socket = None - - def _serverloop(self): - while self._listening: - self._serve() - - def _serve(self): - if self._verbose: print("Wait for connection ...") - conn, address = self._socket.accept() - if self._verbose: print("Accepted connection from %s" % repr(address)) - if not self._verify(conn, address): - print("*** Connection from %s refused" % repr(address)) - conn.close() - return - rf = conn.makefile('r') - wf = conn.makefile('w') - ok = 1 - while ok: - wf.flush() - if self._verbose > 1: print("Wait for next request ...") - ok = self._dorequest(rf, wf) - - _valid = ['192.16.201.*', '192.16.197.*', '132.151.1.*', '129.6.64.*'] - - def _verify(self, conn, address): - host, port = address - for pat in self._valid: - if fnmatch(host, pat): return 1 - return 0 - - def _dorequest(self, rf, wf): - rp = pickle.Unpickler(rf) - try: - request = rp.load() - except EOFError: - return 0 - if self._verbose > 1: print("Got request: %s" % repr(request)) - try: - methodname, args, id = request - if '.' in methodname: - reply = (None, self._special(methodname, args), id) - elif methodname[0] == '_': - raise NameError("illegal method name %s" % repr(methodname)) - else: - method = getattr(self, methodname) - reply = (None, method(*args), id) - except: - reply = (sys.exc_info()[:2], id) - if id < 0 and reply[:2] == (None, None): - if self._verbose > 1: print("Suppress reply") - return 1 - if self._verbose > 1: print("Send reply: %s" % repr(reply)) - wp = pickle.Pickler(wf) - wp.dump(reply) - return 1 - - def _special(self, methodname, args): - if methodname == '.methods': - if not hasattr(self, '_methods'): - self._methods = tuple(self._listmethods()) - return self._methods - raise NameError("unrecognized special method name %s" % repr(methodname)) - - def _listmethods(self, cl=None): - if not cl: cl = self.__class__ - names = sorted([x for x in cl.__dict__.keys() if x[0] != '_']) - for base in cl.__bases__: - basenames = self._listmethods(base) - basenames = list(filter(lambda x, names=names: x not in names, basenames)) - names[len(names):] = basenames - return names - - -from security import Security - - -class SecureServer(Server, Security): - - def __init__(self, *args): - Server.__init__(self, *args) - Security.__init__(self) - - def _verify(self, conn, address): - import string - challenge = self._generate_challenge() - conn.send("%d\n" % challenge) - response = "" - while "\n" not in response and len(response) < 100: - data = conn.recv(100) - if not data: - break - response = response + data - try: - response = string.atol(string.strip(response)) - except string.atol_error: - if self._verbose > 0: - print("Invalid response syntax", repr(response)) - return 0 - if not self._compare_challenge_response(challenge, response): - if self._verbose > 0: - print("Invalid response value", repr(response)) - return 0 - if self._verbose > 1: - print("Response matches challenge. Go ahead!") - return 1 diff --git a/Demo/pdist/sumtree.py b/Demo/pdist/sumtree.py deleted file mode 100644 index 92e7771..0000000 --- a/Demo/pdist/sumtree.py +++ /dev/null @@ -1,27 +0,0 @@ -import time -import sys -import FSProxy - -def main(): - t1 = time.time() - #proxy = FSProxy.FSProxyClient(('voorn.cwi.nl', 4127)) - proxy = FSProxy.FSProxyLocal() - sumtree(proxy) - proxy._close() - t2 = time.time() - print(t2-t1, "seconds") - sys.stdout.write("[Return to exit] ") - sys.stdout.flush() - sys.stdin.readline() - -def sumtree(proxy): - print("PWD =", proxy.pwd()) - files = proxy.listfiles() - proxy.infolist(files) - subdirs = proxy.listsubdirs() - for name in subdirs: - proxy.cd(name) - sumtree(proxy) - proxy.back() - -main() |