summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Demo/README3
-rw-r--r--Demo/pdist/FSProxy.py301
-rwxr-xr-xDemo/pdist/RCSProxy.py198
-rw-r--r--Demo/pdist/README121
-rw-r--r--Demo/pdist/client.py156
-rw-r--r--Demo/pdist/cmdfw.py142
-rw-r--r--Demo/pdist/cmptree.py213
-rw-r--r--Demo/pdist/cvslib.py359
-rw-r--r--Demo/pdist/cvslock.py279
-rw-r--r--Demo/pdist/mac.py24
-rwxr-xr-xDemo/pdist/makechangelog.py109
-rwxr-xr-xDemo/pdist/rcsbump33
-rw-r--r--Demo/pdist/rcsclient.py71
-rw-r--r--Demo/pdist/rcslib.py334
-rwxr-xr-xDemo/pdist/rcvs8
-rwxr-xr-xDemo/pdist/rcvs.py476
-rwxr-xr-xDemo/pdist/rrcs8
-rwxr-xr-xDemo/pdist/rrcs.py158
-rw-r--r--Demo/pdist/security.py33
-rw-r--r--Demo/pdist/server.py143
-rw-r--r--Demo/pdist/sumtree.py27
21 files changed, 0 insertions, 3196 deletions
diff --git a/Demo/README b/Demo/README
index 1ed1ff1..8af3420 100644
--- a/Demo/README
+++ b/Demo/README
@@ -35,9 +35,6 @@ newmetaclasses Demonstration of metaclasses.
parser Example using the parser module.
-pdist Old, unfinished code messing with CVS, RCS and remote
- files.
-
pysvr An example of embedding Python in a threaded
application.
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()