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