##// END OF EJS Templates
Use UnexpectedOutput exception instead of RepoError in sshrepo, too.
Thomas Arendsen Hein -
r3766:58166524 default
parent child Browse files
Show More
@@ -1,224 +1,224 b''
1 # sshrepo.py - ssh repository proxy class for mercurial
1 # sshrepo.py - ssh repository proxy class for mercurial
2 #
2 #
3 # Copyright 2005, 2006 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005, 2006 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms
5 # This software may be used and distributed according to the terms
6 # of the GNU General Public License, incorporated herein by reference.
6 # of the GNU General Public License, incorporated herein by reference.
7
7
8 from node import *
8 from node import *
9 from remoterepo import *
9 from remoterepo import *
10 from i18n import gettext as _
10 from i18n import gettext as _
11 from demandload import *
11 from demandload import *
12 demandload(globals(), "hg os re stat util")
12 demandload(globals(), "hg os re stat util")
13
13
14 class sshrepository(remoterepository):
14 class sshrepository(remoterepository):
15 def __init__(self, ui, path, create=0):
15 def __init__(self, ui, path, create=0):
16 self._url = path
16 self._url = path
17 self.ui = ui
17 self.ui = ui
18
18
19 m = re.match(r'^ssh://(([^@]+)@)?([^:/]+)(:(\d+))?(/(.*))?$', path)
19 m = re.match(r'^ssh://(([^@]+)@)?([^:/]+)(:(\d+))?(/(.*))?$', path)
20 if not m:
20 if not m:
21 self.raise_(hg.RepoError(_("couldn't parse location %s") % path))
21 self.raise_(hg.RepoError(_("couldn't parse location %s") % path))
22
22
23 self.user = m.group(2)
23 self.user = m.group(2)
24 self.host = m.group(3)
24 self.host = m.group(3)
25 self.port = m.group(5)
25 self.port = m.group(5)
26 self.path = m.group(7) or "."
26 self.path = m.group(7) or "."
27
27
28 args = self.user and ("%s@%s" % (self.user, self.host)) or self.host
28 args = self.user and ("%s@%s" % (self.user, self.host)) or self.host
29 args = self.port and ("%s -p %s") % (args, self.port) or args
29 args = self.port and ("%s -p %s") % (args, self.port) or args
30
30
31 sshcmd = self.ui.config("ui", "ssh", "ssh")
31 sshcmd = self.ui.config("ui", "ssh", "ssh")
32 remotecmd = self.ui.config("ui", "remotecmd", "hg")
32 remotecmd = self.ui.config("ui", "remotecmd", "hg")
33
33
34 if create:
34 if create:
35 cmd = '%s %s "%s init %s"'
35 cmd = '%s %s "%s init %s"'
36 cmd = cmd % (sshcmd, args, remotecmd, self.path)
36 cmd = cmd % (sshcmd, args, remotecmd, self.path)
37
37
38 ui.note('running %s\n' % cmd)
38 ui.note('running %s\n' % cmd)
39 res = os.system(cmd)
39 res = os.system(cmd)
40 if res != 0:
40 if res != 0:
41 self.raise_(hg.RepoError(_("could not create remote repo")))
41 self.raise_(hg.RepoError(_("could not create remote repo")))
42
42
43 self.validate_repo(ui, sshcmd, args, remotecmd)
43 self.validate_repo(ui, sshcmd, args, remotecmd)
44
44
45 def url(self):
45 def url(self):
46 return self._url
46 return self._url
47
47
48 def validate_repo(self, ui, sshcmd, args, remotecmd):
48 def validate_repo(self, ui, sshcmd, args, remotecmd):
49 # cleanup up previous run
49 # cleanup up previous run
50 self.cleanup()
50 self.cleanup()
51
51
52 cmd = '%s %s "%s -R %s serve --stdio"'
52 cmd = '%s %s "%s -R %s serve --stdio"'
53 cmd = cmd % (sshcmd, args, remotecmd, self.path)
53 cmd = cmd % (sshcmd, args, remotecmd, self.path)
54
54
55 ui.note('running %s\n' % cmd)
55 ui.note('running %s\n' % cmd)
56 self.pipeo, self.pipei, self.pipee = os.popen3(cmd, 'b')
56 self.pipeo, self.pipei, self.pipee = os.popen3(cmd, 'b')
57
57
58 # skip any noise generated by remote shell
58 # skip any noise generated by remote shell
59 self.do_cmd("hello")
59 self.do_cmd("hello")
60 r = self.do_cmd("between", pairs=("%s-%s" % ("0"*40, "0"*40)))
60 r = self.do_cmd("between", pairs=("%s-%s" % ("0"*40, "0"*40)))
61 lines = ["", "dummy"]
61 lines = ["", "dummy"]
62 max_noise = 500
62 max_noise = 500
63 while lines[-1] and max_noise:
63 while lines[-1] and max_noise:
64 l = r.readline()
64 l = r.readline()
65 self.readerr()
65 self.readerr()
66 if lines[-1] == "1\n" and l == "\n":
66 if lines[-1] == "1\n" and l == "\n":
67 break
67 break
68 if l:
68 if l:
69 ui.debug(_("remote: "), l)
69 ui.debug(_("remote: "), l)
70 lines.append(l)
70 lines.append(l)
71 max_noise -= 1
71 max_noise -= 1
72 else:
72 else:
73 self.raise_(hg.RepoError(_("no suitable response from remote hg")))
73 self.raise_(hg.RepoError(_("no suitable response from remote hg")))
74
74
75 self.capabilities = ()
75 self.capabilities = ()
76 lines.reverse()
76 lines.reverse()
77 for l in lines:
77 for l in lines:
78 if l.startswith("capabilities:"):
78 if l.startswith("capabilities:"):
79 self.capabilities = l[:-1].split(":")[1].split()
79 self.capabilities = l[:-1].split(":")[1].split()
80 break
80 break
81
81
82 def readerr(self):
82 def readerr(self):
83 while 1:
83 while 1:
84 size = util.fstat(self.pipee).st_size
84 size = util.fstat(self.pipee).st_size
85 if size == 0: break
85 if size == 0: break
86 l = self.pipee.readline()
86 l = self.pipee.readline()
87 if not l: break
87 if not l: break
88 self.ui.status(_("remote: "), l)
88 self.ui.status(_("remote: "), l)
89
89
90 def raise_(self, exception):
90 def raise_(self, exception):
91 self.cleanup()
91 self.cleanup()
92 raise exception
92 raise exception
93
93
94 def cleanup(self):
94 def cleanup(self):
95 try:
95 try:
96 self.pipeo.close()
96 self.pipeo.close()
97 self.pipei.close()
97 self.pipei.close()
98 # read the error descriptor until EOF
98 # read the error descriptor until EOF
99 for l in self.pipee:
99 for l in self.pipee:
100 self.ui.status(_("remote: "), l)
100 self.ui.status(_("remote: "), l)
101 self.pipee.close()
101 self.pipee.close()
102 except:
102 except:
103 pass
103 pass
104
104
105 __del__ = cleanup
105 __del__ = cleanup
106
106
107 def do_cmd(self, cmd, **args):
107 def do_cmd(self, cmd, **args):
108 self.ui.debug(_("sending %s command\n") % cmd)
108 self.ui.debug(_("sending %s command\n") % cmd)
109 self.pipeo.write("%s\n" % cmd)
109 self.pipeo.write("%s\n" % cmd)
110 for k, v in args.items():
110 for k, v in args.items():
111 self.pipeo.write("%s %d\n" % (k, len(v)))
111 self.pipeo.write("%s %d\n" % (k, len(v)))
112 self.pipeo.write(v)
112 self.pipeo.write(v)
113 self.pipeo.flush()
113 self.pipeo.flush()
114
114
115 return self.pipei
115 return self.pipei
116
116
117 def call(self, cmd, **args):
117 def call(self, cmd, **args):
118 r = self.do_cmd(cmd, **args)
118 r = self.do_cmd(cmd, **args)
119 l = r.readline()
119 l = r.readline()
120 self.readerr()
120 self.readerr()
121 try:
121 try:
122 l = int(l)
122 l = int(l)
123 except:
123 except:
124 self.raise_(hg.RepoError(_("unexpected response '%s'") % l))
124 self.raise_(util.UnexpectedOutput(_("unexpected response:"), l))
125 return r.read(l)
125 return r.read(l)
126
126
127 def lock(self):
127 def lock(self):
128 self.call("lock")
128 self.call("lock")
129 return remotelock(self)
129 return remotelock(self)
130
130
131 def unlock(self):
131 def unlock(self):
132 self.call("unlock")
132 self.call("unlock")
133
133
134 def lookup(self, key):
134 def lookup(self, key):
135 d = self.call("lookup", key=key)
135 d = self.call("lookup", key=key)
136 success, data = d[:-1].split(" ", 1)
136 success, data = d[:-1].split(" ", 1)
137 if int(success):
137 if int(success):
138 return bin(data)
138 return bin(data)
139 else:
139 else:
140 self.raise_(hg.RepoError(data))
140 self.raise_(hg.RepoError(data))
141
141
142 def heads(self):
142 def heads(self):
143 d = self.call("heads")
143 d = self.call("heads")
144 try:
144 try:
145 return map(bin, d[:-1].split(" "))
145 return map(bin, d[:-1].split(" "))
146 except:
146 except:
147 self.raise_(hg.RepoError(_("unexpected response '%s'") % (d[:400] + "...")))
147 self.raise_(util.UnexpectedOutput(_("unexpected response:"), d))
148
148
149 def branches(self, nodes):
149 def branches(self, nodes):
150 n = " ".join(map(hex, nodes))
150 n = " ".join(map(hex, nodes))
151 d = self.call("branches", nodes=n)
151 d = self.call("branches", nodes=n)
152 try:
152 try:
153 br = [ tuple(map(bin, b.split(" "))) for b in d.splitlines() ]
153 br = [ tuple(map(bin, b.split(" "))) for b in d.splitlines() ]
154 return br
154 return br
155 except:
155 except:
156 self.raise_(hg.RepoError(_("unexpected response '%s'") % (d[:400] + "...")))
156 self.raise_(util.UnexpectedOutput(_("unexpected response:"), d))
157
157
158 def between(self, pairs):
158 def between(self, pairs):
159 n = "\n".join(["-".join(map(hex, p)) for p in pairs])
159 n = "\n".join(["-".join(map(hex, p)) for p in pairs])
160 d = self.call("between", pairs=n)
160 d = self.call("between", pairs=n)
161 try:
161 try:
162 p = [ l and map(bin, l.split(" ")) or [] for l in d.splitlines() ]
162 p = [ l and map(bin, l.split(" ")) or [] for l in d.splitlines() ]
163 return p
163 return p
164 except:
164 except:
165 self.raise_(hg.RepoError(_("unexpected response '%s'") % (d[:400] + "...")))
165 self.raise_(util.UnexpectedOutput(_("unexpected response:"), d))
166
166
167 def changegroup(self, nodes, kind):
167 def changegroup(self, nodes, kind):
168 n = " ".join(map(hex, nodes))
168 n = " ".join(map(hex, nodes))
169 return self.do_cmd("changegroup", roots=n)
169 return self.do_cmd("changegroup", roots=n)
170
170
171 def changegroupsubset(self, bases, heads, kind):
171 def changegroupsubset(self, bases, heads, kind):
172 bases = " ".join(map(hex, bases))
172 bases = " ".join(map(hex, bases))
173 heads = " ".join(map(hex, heads))
173 heads = " ".join(map(hex, heads))
174 return self.do_cmd("changegroupsubset", bases=bases, heads=heads)
174 return self.do_cmd("changegroupsubset", bases=bases, heads=heads)
175
175
176 def unbundle(self, cg, heads, source):
176 def unbundle(self, cg, heads, source):
177 d = self.call("unbundle", heads=' '.join(map(hex, heads)))
177 d = self.call("unbundle", heads=' '.join(map(hex, heads)))
178 if d:
178 if d:
179 self.raise_(hg.RepoError(_("push refused: %s") % d))
179 self.raise_(hg.RepoError(_("push refused: %s") % d))
180
180
181 while 1:
181 while 1:
182 d = cg.read(4096)
182 d = cg.read(4096)
183 if not d: break
183 if not d: break
184 self.pipeo.write(str(len(d)) + '\n')
184 self.pipeo.write(str(len(d)) + '\n')
185 self.pipeo.write(d)
185 self.pipeo.write(d)
186 self.readerr()
186 self.readerr()
187
187
188 self.pipeo.write('0\n')
188 self.pipeo.write('0\n')
189 self.pipeo.flush()
189 self.pipeo.flush()
190
190
191 self.readerr()
191 self.readerr()
192 d = self.pipei.readline()
192 d = self.pipei.readline()
193 if d != '\n':
193 if d != '\n':
194 return 1
194 return 1
195
195
196 l = int(self.pipei.readline())
196 l = int(self.pipei.readline())
197 r = self.pipei.read(l)
197 r = self.pipei.read(l)
198 if not r:
198 if not r:
199 return 1
199 return 1
200 return int(r)
200 return int(r)
201
201
202 def addchangegroup(self, cg, source, url):
202 def addchangegroup(self, cg, source, url):
203 d = self.call("addchangegroup")
203 d = self.call("addchangegroup")
204 if d:
204 if d:
205 self.raise_(hg.RepoError(_("push refused: %s") % d))
205 self.raise_(hg.RepoError(_("push refused: %s") % d))
206 while 1:
206 while 1:
207 d = cg.read(4096)
207 d = cg.read(4096)
208 if not d: break
208 if not d: break
209 self.pipeo.write(d)
209 self.pipeo.write(d)
210 self.readerr()
210 self.readerr()
211
211
212 self.pipeo.flush()
212 self.pipeo.flush()
213
213
214 self.readerr()
214 self.readerr()
215 l = int(self.pipei.readline())
215 l = int(self.pipei.readline())
216 r = self.pipei.read(l)
216 r = self.pipei.read(l)
217 if not r:
217 if not r:
218 return 1
218 return 1
219 return int(r)
219 return int(r)
220
220
221 def stream_out(self):
221 def stream_out(self):
222 return self.do_cmd('stream_out')
222 return self.do_cmd('stream_out')
223
223
224 instance = sshrepository
224 instance = sshrepository
General Comments 0
You need to be logged in to leave comments. Login now