RCSProxy.py 4.61 KB
Newer Older
1
#! /usr/bin/env python
Guido van Rossum's avatar
Guido van Rossum committed
2 3 4 5 6 7 8 9

"""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.

10
The module defines two classes:
Guido van Rossum's avatar
Guido van Rossum committed
11 12 13

RCSProxyLocal  -- used for local access
RCSProxyServer -- used on the server side of remote access
14

15 16
The corresponding client class, RCSProxyClient, is defined in module
rcsclient.
Guido van Rossum's avatar
Guido van Rossum committed
17 18 19 20 21 22 23 24 25 26 27

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
28 29 30 31 32 33
import rcslib


class DirSupport:

    def __init__(self):
Guido van Rossum's avatar
Guido van Rossum committed
34
        self._dirstack = []
35 36

    def __del__(self):
Guido van Rossum's avatar
Guido van Rossum committed
37
        self._close()
38 39

    def _close(self):
Guido van Rossum's avatar
Guido van Rossum committed
40 41
        while self._dirstack:
            self.back()
42 43

    def pwd(self):
Guido van Rossum's avatar
Guido van Rossum committed
44
        return os.getcwd()
45 46

    def cd(self, name):
Guido van Rossum's avatar
Guido van Rossum committed
47 48 49
        save = os.getcwd()
        os.chdir(name)
        self._dirstack.append(save)
50 51

    def back(self):
Guido van Rossum's avatar
Guido van Rossum committed
52 53 54 55 56
        if not self._dirstack:
            raise os.error, "empty directory stack"
        dir = self._dirstack[-1]
        os.chdir(dir)
        del self._dirstack[-1]
57 58

    def listsubdirs(self, pat = None):
Guido van Rossum's avatar
Guido van Rossum committed
59 60 61
        files = os.listdir(os.curdir)
        files = filter(os.path.isdir, files)
        return self._filter(files, pat)
62 63

    def isdir(self, name):
Guido van Rossum's avatar
Guido van Rossum committed
64
        return os.path.isdir(name)
65 66

    def mkdir(self, name):
Guido van Rossum's avatar
Guido van Rossum committed
67
        os.mkdir(name, 0777)
68 69

    def rmdir(self, name):
Guido van Rossum's avatar
Guido van Rossum committed
70
        os.rmdir(name)
71

Guido van Rossum's avatar
Guido van Rossum committed
72

73
class RCSProxyLocal(rcslib.RCS, DirSupport):
Guido van Rossum's avatar
Guido van Rossum committed
74

75
    def __init__(self):
Guido van Rossum's avatar
Guido van Rossum committed
76 77
        rcslib.RCS.__init__(self)
        DirSupport.__init__(self)
78 79

    def __del__(self):
Guido van Rossum's avatar
Guido van Rossum committed
80 81
        DirSupport.__del__(self)
        rcslib.RCS.__del__(self)
82 83

    def sumlist(self, list = None):
Guido van Rossum's avatar
Guido van Rossum committed
84
        return self._list(self.sum, list)
85 86

    def sumdict(self, list = None):
Guido van Rossum's avatar
Guido van Rossum committed
87
        return self._dict(self.sum, list)
88 89

    def sum(self, name_rev):
Guido van Rossum's avatar
Guido van Rossum committed
90 91 92 93 94 95 96 97 98 99
        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()
100 101

    def get(self, name_rev):
Guido van Rossum's avatar
Guido van Rossum committed
102 103 104 105
        f = self._open(name_rev)
        data = f.read()
        self._closepipe(f)
        return data
106 107

    def put(self, name_rev, data, message=None):
Guido van Rossum's avatar
Guido van Rossum committed
108 109 110 111 112 113
        name, rev = self._unmangle(name_rev)
        f = open(name, 'w')
        f.write(data)
        f.close()
        self.checkin(name_rev, message)
        self._remove(name)
114 115

    def _list(self, function, list = None):
Guido van Rossum's avatar
Guido van Rossum committed
116
        """INTERNAL: apply FUNCTION to all files in LIST.
117

Guido van Rossum's avatar
Guido van Rossum committed
118
        Return a list of the results.
119

Guido van Rossum's avatar
Guido van Rossum committed
120
        The list defaults to all files in the directory if None.
121

Guido van Rossum's avatar
Guido van Rossum committed
122 123 124 125 126 127 128 129 130 131
        """
        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
132 133

    def _dict(self, function, list = None):
Guido van Rossum's avatar
Guido van Rossum committed
134
        """INTERNAL: apply FUNCTION to all files in LIST.
135

Guido van Rossum's avatar
Guido van Rossum committed
136
        Return a dictionary mapping files to results.
137

Guido van Rossum's avatar
Guido van Rossum committed
138
        The list defaults to all files in the directory if None.
139

Guido van Rossum's avatar
Guido van Rossum committed
140 141 142 143 144 145 146 147 148 149
        """
        if list is None:
            list = self.listfiles()
        dict = {}
        for name in list:
            try:
                dict[name] = function(name)
            except (os.error, IOError):
                pass
        return dict
Guido van Rossum's avatar
Guido van Rossum committed
150 151


Guido van Rossum's avatar
Guido van Rossum committed
152
class RCSProxyServer(RCSProxyLocal, server.SecureServer):
153 154

    def __init__(self, address, verbose = server.VERBOSE):
Guido van Rossum's avatar
Guido van Rossum committed
155 156
        RCSProxyLocal.__init__(self)
        server.SecureServer.__init__(self, address, verbose)
157 158

    def _close(self):
Guido van Rossum's avatar
Guido van Rossum committed
159 160
        server.SecureServer._close(self)
        RCSProxyLocal._close(self)
161 162

    def _serve(self):
Guido van Rossum's avatar
Guido van Rossum committed
163 164 165
        server.SecureServer._serve(self)
        # Retreat into start directory
        while self._dirstack: self.back()
Guido van Rossum's avatar
Guido van Rossum committed
166 167 168


def test_server():
169 170 171
    import string
    import sys
    if sys.argv[1:]:
Guido van Rossum's avatar
Guido van Rossum committed
172
        port = string.atoi(sys.argv[1])
173
    else:
Guido van Rossum's avatar
Guido van Rossum committed
174
        port = 4127
175 176
    proxy = RCSProxyServer(('', port))
    proxy._serverloop()
Guido van Rossum's avatar
Guido van Rossum committed
177 178 179


def test():
180 181
    import sys
    if not sys.argv[1:] or sys.argv[1] and sys.argv[1][0] in '0123456789':
Guido van Rossum's avatar
Guido van Rossum committed
182 183
        test_server()
        sys.exit(0)
184 185 186
    proxy = RCSProxyLocal()
    what = sys.argv[1]
    if hasattr(proxy, what):
Guido van Rossum's avatar
Guido van Rossum committed
187 188 189 190
        attr = getattr(proxy, what)
        if callable(attr):
            print apply(attr, tuple(sys.argv[2:]))
        else:
191
            print repr(attr)
192
    else:
Guido van Rossum's avatar
Guido van Rossum committed
193 194
        print "%s: no such attribute" % what
        sys.exit(2)
Guido van Rossum's avatar
Guido van Rossum committed
195 196 197


if __name__ == '__main__':
198
    test()