#! /usr/bin/env python

"""RCS Proxy.

Provide a simplified interface on RCS files, locally or remotely.
The functionality is geared towards implementing some sort of
remote CVS like utility.  It is modeled after the similar module
FSProxy.

The module defines 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 = filter(os.path.isdir, files)
        return self._filter(files, pat)

    def isdir(self, name):
        return os.path.isdir(name)

    def mkdir(self, name):
        os.mkdir(name, 0777)

    def rmdir(self, name):
        os.rmdir(name)


class RCSProxyLocal(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 callable(attr):
            print apply(attr, tuple(sys.argv[2:]))
        else:
            print repr(attr)
    else:
        print "%s: no such attribute" % what
        sys.exit(2)


if __name__ == '__main__':
    test()
