Guido van Rossum | f06ee5f | 1996-11-27 19:52:01 +0000 | [diff] [blame] | 1 | #! /usr/bin/env python |
Guido van Rossum | 5f07b84 | 1995-04-26 22:57:11 +0000 | [diff] [blame] | 2 | |
| 3 | """RCS Proxy. |
| 4 | |
| 5 | Provide a simplified interface on RCS files, locally or remotely. |
| 6 | The functionality is geared towards implementing some sort of |
| 7 | remote CVS like utility. It is modeled after the similar module |
| 8 | FSProxy. |
| 9 | |
Guido van Rossum | ab75eb2 | 1995-06-23 22:07:17 +0000 | [diff] [blame] | 10 | The module defines two classes: |
Guido van Rossum | 5f07b84 | 1995-04-26 22:57:11 +0000 | [diff] [blame] | 11 | |
| 12 | RCSProxyLocal -- used for local access |
| 13 | RCSProxyServer -- used on the server side of remote access |
Guido van Rossum | ab75eb2 | 1995-06-23 22:07:17 +0000 | [diff] [blame] | 14 | |
Guido van Rossum | bab4725 | 1995-06-23 22:37:53 +0000 | [diff] [blame] | 15 | The corresponding client class, RCSProxyClient, is defined in module |
| 16 | rcsclient. |
Guido van Rossum | 5f07b84 | 1995-04-26 22:57:11 +0000 | [diff] [blame] | 17 | |
| 18 | The remote classes are instantiated with an IP address and an optional |
| 19 | verbosity flag. |
| 20 | """ |
| 21 | |
| 22 | import server |
Guido van Rossum | 5f07b84 | 1995-04-26 22:57:11 +0000 | [diff] [blame] | 23 | import md5 |
| 24 | import os |
| 25 | import fnmatch |
| 26 | import string |
| 27 | import tempfile |
Guido van Rossum | ab75eb2 | 1995-06-23 22:07:17 +0000 | [diff] [blame] | 28 | import rcslib |
Guido van Rossum | 5f07b84 | 1995-04-26 22:57:11 +0000 | [diff] [blame] | 29 | |
| 30 | |
Guido van Rossum | ab75eb2 | 1995-06-23 22:07:17 +0000 | [diff] [blame] | 31 | class DirSupport: |
| 32 | |
| 33 | def __init__(self): |
Guido van Rossum | 4117e54 | 1998-09-14 16:44:15 +0000 | [diff] [blame] | 34 | self._dirstack = [] |
Guido van Rossum | ab75eb2 | 1995-06-23 22:07:17 +0000 | [diff] [blame] | 35 | |
| 36 | def __del__(self): |
Guido van Rossum | 4117e54 | 1998-09-14 16:44:15 +0000 | [diff] [blame] | 37 | self._close() |
Guido van Rossum | ab75eb2 | 1995-06-23 22:07:17 +0000 | [diff] [blame] | 38 | |
| 39 | def _close(self): |
Guido van Rossum | 4117e54 | 1998-09-14 16:44:15 +0000 | [diff] [blame] | 40 | while self._dirstack: |
| 41 | self.back() |
Guido van Rossum | ab75eb2 | 1995-06-23 22:07:17 +0000 | [diff] [blame] | 42 | |
| 43 | def pwd(self): |
Guido van Rossum | 4117e54 | 1998-09-14 16:44:15 +0000 | [diff] [blame] | 44 | return os.getcwd() |
Guido van Rossum | ab75eb2 | 1995-06-23 22:07:17 +0000 | [diff] [blame] | 45 | |
| 46 | def cd(self, name): |
Guido van Rossum | 4117e54 | 1998-09-14 16:44:15 +0000 | [diff] [blame] | 47 | save = os.getcwd() |
| 48 | os.chdir(name) |
| 49 | self._dirstack.append(save) |
Guido van Rossum | ab75eb2 | 1995-06-23 22:07:17 +0000 | [diff] [blame] | 50 | |
| 51 | def back(self): |
Guido van Rossum | 4117e54 | 1998-09-14 16:44:15 +0000 | [diff] [blame] | 52 | if not self._dirstack: |
| 53 | raise os.error, "empty directory stack" |
| 54 | dir = self._dirstack[-1] |
| 55 | os.chdir(dir) |
| 56 | del self._dirstack[-1] |
Guido van Rossum | ab75eb2 | 1995-06-23 22:07:17 +0000 | [diff] [blame] | 57 | |
| 58 | def listsubdirs(self, pat = None): |
Guido van Rossum | 4117e54 | 1998-09-14 16:44:15 +0000 | [diff] [blame] | 59 | files = os.listdir(os.curdir) |
| 60 | files = filter(os.path.isdir, files) |
| 61 | return self._filter(files, pat) |
Guido van Rossum | ab75eb2 | 1995-06-23 22:07:17 +0000 | [diff] [blame] | 62 | |
| 63 | def isdir(self, name): |
Guido van Rossum | 4117e54 | 1998-09-14 16:44:15 +0000 | [diff] [blame] | 64 | return os.path.isdir(name) |
Guido van Rossum | ab75eb2 | 1995-06-23 22:07:17 +0000 | [diff] [blame] | 65 | |
| 66 | def mkdir(self, name): |
Guido van Rossum | 4117e54 | 1998-09-14 16:44:15 +0000 | [diff] [blame] | 67 | os.mkdir(name, 0777) |
Guido van Rossum | ab75eb2 | 1995-06-23 22:07:17 +0000 | [diff] [blame] | 68 | |
| 69 | def rmdir(self, name): |
Guido van Rossum | 4117e54 | 1998-09-14 16:44:15 +0000 | [diff] [blame] | 70 | os.rmdir(name) |
Guido van Rossum | 5f07b84 | 1995-04-26 22:57:11 +0000 | [diff] [blame] | 71 | |
| 72 | |
Guido van Rossum | ab75eb2 | 1995-06-23 22:07:17 +0000 | [diff] [blame] | 73 | class RCSProxyLocal(rcslib.RCS, DirSupport): |
Guido van Rossum | 5f07b84 | 1995-04-26 22:57:11 +0000 | [diff] [blame] | 74 | |
Guido van Rossum | ab75eb2 | 1995-06-23 22:07:17 +0000 | [diff] [blame] | 75 | def __init__(self): |
Guido van Rossum | 4117e54 | 1998-09-14 16:44:15 +0000 | [diff] [blame] | 76 | rcslib.RCS.__init__(self) |
| 77 | DirSupport.__init__(self) |
Guido van Rossum | 5f07b84 | 1995-04-26 22:57:11 +0000 | [diff] [blame] | 78 | |
Guido van Rossum | ab75eb2 | 1995-06-23 22:07:17 +0000 | [diff] [blame] | 79 | def __del__(self): |
Guido van Rossum | 4117e54 | 1998-09-14 16:44:15 +0000 | [diff] [blame] | 80 | DirSupport.__del__(self) |
| 81 | rcslib.RCS.__del__(self) |
Guido van Rossum | 5f07b84 | 1995-04-26 22:57:11 +0000 | [diff] [blame] | 82 | |
Guido van Rossum | ab75eb2 | 1995-06-23 22:07:17 +0000 | [diff] [blame] | 83 | def sumlist(self, list = None): |
Guido van Rossum | 4117e54 | 1998-09-14 16:44:15 +0000 | [diff] [blame] | 84 | return self._list(self.sum, list) |
Guido van Rossum | 5f07b84 | 1995-04-26 22:57:11 +0000 | [diff] [blame] | 85 | |
Guido van Rossum | ab75eb2 | 1995-06-23 22:07:17 +0000 | [diff] [blame] | 86 | def sumdict(self, list = None): |
Guido van Rossum | 4117e54 | 1998-09-14 16:44:15 +0000 | [diff] [blame] | 87 | return self._dict(self.sum, list) |
Guido van Rossum | 5f07b84 | 1995-04-26 22:57:11 +0000 | [diff] [blame] | 88 | |
Guido van Rossum | ab75eb2 | 1995-06-23 22:07:17 +0000 | [diff] [blame] | 89 | def sum(self, name_rev): |
Guido van Rossum | 4117e54 | 1998-09-14 16:44:15 +0000 | [diff] [blame] | 90 | f = self._open(name_rev) |
| 91 | BUFFERSIZE = 1024*8 |
| 92 | sum = md5.new() |
| 93 | while 1: |
| 94 | buffer = f.read(BUFFERSIZE) |
| 95 | if not buffer: |
| 96 | break |
| 97 | sum.update(buffer) |
| 98 | self._closepipe(f) |
| 99 | return sum.digest() |
Guido van Rossum | ab75eb2 | 1995-06-23 22:07:17 +0000 | [diff] [blame] | 100 | |
| 101 | def get(self, name_rev): |
Guido van Rossum | 4117e54 | 1998-09-14 16:44:15 +0000 | [diff] [blame] | 102 | f = self._open(name_rev) |
| 103 | data = f.read() |
| 104 | self._closepipe(f) |
| 105 | return data |
Guido van Rossum | ab75eb2 | 1995-06-23 22:07:17 +0000 | [diff] [blame] | 106 | |
| 107 | def put(self, name_rev, data, message=None): |
Guido van Rossum | 4117e54 | 1998-09-14 16:44:15 +0000 | [diff] [blame] | 108 | name, rev = self._unmangle(name_rev) |
| 109 | f = open(name, 'w') |
| 110 | f.write(data) |
| 111 | f.close() |
| 112 | self.checkin(name_rev, message) |
| 113 | self._remove(name) |
Guido van Rossum | ab75eb2 | 1995-06-23 22:07:17 +0000 | [diff] [blame] | 114 | |
| 115 | def _list(self, function, list = None): |
Guido van Rossum | 4117e54 | 1998-09-14 16:44:15 +0000 | [diff] [blame] | 116 | """INTERNAL: apply FUNCTION to all files in LIST. |
Guido van Rossum | ab75eb2 | 1995-06-23 22:07:17 +0000 | [diff] [blame] | 117 | |
Guido van Rossum | 4117e54 | 1998-09-14 16:44:15 +0000 | [diff] [blame] | 118 | Return a list of the results. |
Guido van Rossum | ab75eb2 | 1995-06-23 22:07:17 +0000 | [diff] [blame] | 119 | |
Guido van Rossum | 4117e54 | 1998-09-14 16:44:15 +0000 | [diff] [blame] | 120 | The list defaults to all files in the directory if None. |
Guido van Rossum | ab75eb2 | 1995-06-23 22:07:17 +0000 | [diff] [blame] | 121 | |
Guido van Rossum | 4117e54 | 1998-09-14 16:44:15 +0000 | [diff] [blame] | 122 | """ |
| 123 | if list is None: |
| 124 | list = self.listfiles() |
| 125 | res = [] |
| 126 | for name in list: |
| 127 | try: |
| 128 | res.append((name, function(name))) |
| 129 | except (os.error, IOError): |
| 130 | res.append((name, None)) |
| 131 | return res |
Guido van Rossum | ab75eb2 | 1995-06-23 22:07:17 +0000 | [diff] [blame] | 132 | |
| 133 | def _dict(self, function, list = None): |
Guido van Rossum | 4117e54 | 1998-09-14 16:44:15 +0000 | [diff] [blame] | 134 | """INTERNAL: apply FUNCTION to all files in LIST. |
Guido van Rossum | ab75eb2 | 1995-06-23 22:07:17 +0000 | [diff] [blame] | 135 | |
Guido van Rossum | 4117e54 | 1998-09-14 16:44:15 +0000 | [diff] [blame] | 136 | Return a dictionary mapping files to results. |
Guido van Rossum | ab75eb2 | 1995-06-23 22:07:17 +0000 | [diff] [blame] | 137 | |
Guido van Rossum | 4117e54 | 1998-09-14 16:44:15 +0000 | [diff] [blame] | 138 | The list defaults to all files in the directory if None. |
Guido van Rossum | ab75eb2 | 1995-06-23 22:07:17 +0000 | [diff] [blame] | 139 | |
Guido van Rossum | 4117e54 | 1998-09-14 16:44:15 +0000 | [diff] [blame] | 140 | """ |
| 141 | if list is None: |
| 142 | list = self.listfiles() |
| 143 | dict = {} |
| 144 | for name in list: |
| 145 | try: |
| 146 | dict[name] = function(name) |
| 147 | except (os.error, IOError): |
| 148 | pass |
| 149 | return dict |
Guido van Rossum | 5f07b84 | 1995-04-26 22:57:11 +0000 | [diff] [blame] | 150 | |
| 151 | |
Guido van Rossum | f3d39ab | 1995-06-21 02:09:20 +0000 | [diff] [blame] | 152 | class RCSProxyServer(RCSProxyLocal, server.SecureServer): |
Guido van Rossum | 5f07b84 | 1995-04-26 22:57:11 +0000 | [diff] [blame] | 153 | |
Guido van Rossum | ab75eb2 | 1995-06-23 22:07:17 +0000 | [diff] [blame] | 154 | def __init__(self, address, verbose = server.VERBOSE): |
Guido van Rossum | 4117e54 | 1998-09-14 16:44:15 +0000 | [diff] [blame] | 155 | RCSProxyLocal.__init__(self) |
| 156 | server.SecureServer.__init__(self, address, verbose) |
Guido van Rossum | 5f07b84 | 1995-04-26 22:57:11 +0000 | [diff] [blame] | 157 | |
Guido van Rossum | ab75eb2 | 1995-06-23 22:07:17 +0000 | [diff] [blame] | 158 | def _close(self): |
Guido van Rossum | 4117e54 | 1998-09-14 16:44:15 +0000 | [diff] [blame] | 159 | server.SecureServer._close(self) |
| 160 | RCSProxyLocal._close(self) |
Guido van Rossum | ab75eb2 | 1995-06-23 22:07:17 +0000 | [diff] [blame] | 161 | |
| 162 | def _serve(self): |
Guido van Rossum | 4117e54 | 1998-09-14 16:44:15 +0000 | [diff] [blame] | 163 | server.SecureServer._serve(self) |
| 164 | # Retreat into start directory |
| 165 | while self._dirstack: self.back() |
Guido van Rossum | 5f07b84 | 1995-04-26 22:57:11 +0000 | [diff] [blame] | 166 | |
| 167 | |
| 168 | def test_server(): |
Guido van Rossum | ab75eb2 | 1995-06-23 22:07:17 +0000 | [diff] [blame] | 169 | import string |
| 170 | import sys |
| 171 | if sys.argv[1:]: |
Guido van Rossum | 4117e54 | 1998-09-14 16:44:15 +0000 | [diff] [blame] | 172 | port = string.atoi(sys.argv[1]) |
Guido van Rossum | ab75eb2 | 1995-06-23 22:07:17 +0000 | [diff] [blame] | 173 | else: |
Guido van Rossum | 4117e54 | 1998-09-14 16:44:15 +0000 | [diff] [blame] | 174 | port = 4127 |
Guido van Rossum | ab75eb2 | 1995-06-23 22:07:17 +0000 | [diff] [blame] | 175 | proxy = RCSProxyServer(('', port)) |
| 176 | proxy._serverloop() |
Guido van Rossum | 5f07b84 | 1995-04-26 22:57:11 +0000 | [diff] [blame] | 177 | |
| 178 | |
| 179 | def test(): |
Guido van Rossum | ab75eb2 | 1995-06-23 22:07:17 +0000 | [diff] [blame] | 180 | import sys |
| 181 | if not sys.argv[1:] or sys.argv[1] and sys.argv[1][0] in '0123456789': |
Guido van Rossum | 4117e54 | 1998-09-14 16:44:15 +0000 | [diff] [blame] | 182 | test_server() |
| 183 | sys.exit(0) |
Guido van Rossum | ab75eb2 | 1995-06-23 22:07:17 +0000 | [diff] [blame] | 184 | proxy = RCSProxyLocal() |
| 185 | what = sys.argv[1] |
| 186 | if hasattr(proxy, what): |
Guido van Rossum | 4117e54 | 1998-09-14 16:44:15 +0000 | [diff] [blame] | 187 | attr = getattr(proxy, what) |
| 188 | if callable(attr): |
| 189 | print apply(attr, tuple(sys.argv[2:])) |
| 190 | else: |
Walter Dörwald | 70a6b49 | 2004-02-12 17:35:32 +0000 | [diff] [blame] | 191 | print repr(attr) |
Guido van Rossum | ab75eb2 | 1995-06-23 22:07:17 +0000 | [diff] [blame] | 192 | else: |
Guido van Rossum | 4117e54 | 1998-09-14 16:44:15 +0000 | [diff] [blame] | 193 | print "%s: no such attribute" % what |
| 194 | sys.exit(2) |
Guido van Rossum | 5f07b84 | 1995-04-26 22:57:11 +0000 | [diff] [blame] | 195 | |
| 196 | |
| 197 | if __name__ == '__main__': |
Guido van Rossum | ab75eb2 | 1995-06-23 22:07:17 +0000 | [diff] [blame] | 198 | test() |