Mercurial > public > mercurial-scm > hg
comparison mercurial/sshrepo.py @ 11586:ddaaaa23bb8f
protocol: move basic ssh client commands to wirerepository
author | Matt Mackall <mpm@selenic.com> |
---|---|
date | Wed, 14 Jul 2010 16:34:57 -0500 |
parents | 02a4373ca5cd |
children | 8a1f625e971d |
comparison
equal
deleted
inserted
replaced
11585:5d907fbb9703 | 11586:ddaaaa23bb8f |
---|---|
5 # This software may be used and distributed according to the terms of the | 5 # This software may be used and distributed according to the terms of the |
6 # GNU General Public License version 2 or any later version. | 6 # GNU General Public License version 2 or any later version. |
7 | 7 |
8 from node import bin, hex | 8 from node import bin, hex |
9 from i18n import _ | 9 from i18n import _ |
10 import repo, util, error, encoding | 10 import repo, util, error, encoding, wireproto |
11 import re, urllib | 11 import re, urllib |
12 | 12 |
13 class remotelock(object): | 13 class remotelock(object): |
14 def __init__(self, repo): | 14 def __init__(self, repo): |
15 self.repo = repo | 15 self.repo = repo |
18 self.repo = None | 18 self.repo = None |
19 def __del__(self): | 19 def __del__(self): |
20 if self.repo: | 20 if self.repo: |
21 self.release() | 21 self.release() |
22 | 22 |
23 class sshrepository(repo.repository): | 23 class sshrepository(wireproto.wirerepository): |
24 def __init__(self, ui, path, create=0): | 24 def __init__(self, ui, path, create=0): |
25 self._url = path | 25 self._url = path |
26 self.ui = ui | 26 self.ui = ui |
27 | 27 |
28 m = re.match(r'^ssh://(([^@]+)@)?([^:/]+)(:(\d+))?(/(.*))?$', path) | 28 m = re.match(r'^ssh://(([^@]+)@)?([^:/]+)(:(\d+))?(/(.*))?$', path) |
99 | 99 |
100 def abort(self, exception): | 100 def abort(self, exception): |
101 self.cleanup() | 101 self.cleanup() |
102 raise exception | 102 raise exception |
103 | 103 |
104 def _abort(self, exception): | |
105 self.cleanup() | |
106 raise exception | |
107 | |
104 def cleanup(self): | 108 def cleanup(self): |
105 try: | 109 try: |
106 self.pipeo.close() | 110 self.pipeo.close() |
107 self.pipei.close() | 111 self.pipei.close() |
108 # read the error descriptor until EOF | 112 # read the error descriptor until EOF |
126 | 130 |
127 def call(self, cmd, **args): | 131 def call(self, cmd, **args): |
128 self.do_cmd(cmd, **args) | 132 self.do_cmd(cmd, **args) |
129 return self._recv() | 133 return self._recv() |
130 | 134 |
135 def _call(self, cmd, **args): | |
136 self.do_cmd(cmd, **args) | |
137 return self._recv() | |
138 | |
131 def _recv(self): | 139 def _recv(self): |
132 l = self.pipei.readline() | 140 l = self.pipei.readline() |
133 self.readerr() | 141 self.readerr() |
134 try: | 142 try: |
135 l = int(l) | 143 l = int(l) |
149 self.call("lock") | 157 self.call("lock") |
150 return remotelock(self) | 158 return remotelock(self) |
151 | 159 |
152 def unlock(self): | 160 def unlock(self): |
153 self.call("unlock") | 161 self.call("unlock") |
154 | |
155 def lookup(self, key): | |
156 self.requirecap('lookup', _('look up remote revision')) | |
157 d = self.call("lookup", key=key) | |
158 success, data = d[:-1].split(" ", 1) | |
159 if int(success): | |
160 return bin(data) | |
161 else: | |
162 self.abort(error.RepoError(data)) | |
163 | |
164 def heads(self): | |
165 d = self.call("heads") | |
166 try: | |
167 return map(bin, d[:-1].split(" ")) | |
168 except: | |
169 self.abort(error.ResponseError(_("unexpected response:"), d)) | |
170 | |
171 def branchmap(self): | |
172 d = self.call("branchmap") | |
173 try: | |
174 branchmap = {} | |
175 for branchpart in d.splitlines(): | |
176 branchheads = branchpart.split(' ') | |
177 branchname = urllib.unquote(branchheads[0]) | |
178 # Earlier servers (1.3.x) send branch names in (their) local | |
179 # charset. The best we can do is assume it's identical to our | |
180 # own local charset, in case it's not utf-8. | |
181 try: | |
182 branchname.decode('utf-8') | |
183 except UnicodeDecodeError: | |
184 branchname = encoding.fromlocal(branchname) | |
185 branchheads = [bin(x) for x in branchheads[1:]] | |
186 branchmap[branchname] = branchheads | |
187 return branchmap | |
188 except: | |
189 raise error.ResponseError(_("unexpected response:"), d) | |
190 | |
191 def branches(self, nodes): | |
192 n = " ".join(map(hex, nodes)) | |
193 d = self.call("branches", nodes=n) | |
194 try: | |
195 br = [tuple(map(bin, b.split(" "))) for b in d.splitlines()] | |
196 return br | |
197 except: | |
198 self.abort(error.ResponseError(_("unexpected response:"), d)) | |
199 | |
200 def between(self, pairs): | |
201 n = " ".join(["-".join(map(hex, p)) for p in pairs]) | |
202 d = self.call("between", pairs=n) | |
203 try: | |
204 p = [l and map(bin, l.split(" ")) or [] for l in d.splitlines()] | |
205 return p | |
206 except: | |
207 self.abort(error.ResponseError(_("unexpected response:"), d)) | |
208 | 162 |
209 def changegroup(self, nodes, kind): | 163 def changegroup(self, nodes, kind): |
210 n = " ".join(map(hex, nodes)) | 164 n = " ".join(map(hex, nodes)) |
211 return self.do_cmd("changegroup", roots=n) | 165 return self.do_cmd("changegroup", roots=n) |
212 | 166 |
271 self.abort(error.ResponseError(_("unexpected response:"), r)) | 225 self.abort(error.ResponseError(_("unexpected response:"), r)) |
272 | 226 |
273 def stream_out(self): | 227 def stream_out(self): |
274 return self.do_cmd('stream_out') | 228 return self.do_cmd('stream_out') |
275 | 229 |
276 def pushkey(self, namespace, key, old, new): | |
277 if not self.capable('pushkey'): | |
278 return False | |
279 d = self.call("pushkey", | |
280 namespace=namespace, key=key, old=old, new=new) | |
281 return bool(int(d)) | |
282 | |
283 def listkeys(self, namespace): | |
284 if not self.capable('pushkey'): | |
285 return {} | |
286 d = self.call("listkeys", namespace=namespace) | |
287 r = {} | |
288 for l in d.splitlines(): | |
289 k, v = l.split('\t') | |
290 r[k.decode('string-escape')] = v.decode('string-escape') | |
291 return r | |
292 | |
293 instance = sshrepository | 230 instance = sshrepository |