##// END OF EJS Templates
sshrepo: when creating a repo, raise an error if it already exists
Benoit Boissinot -
r3036:adf7f342 default
parent child Browse files
Show More
@@ -1,213 +1,214 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 raise hg.RepoError(_("couldn't parse location %s") % path)
21 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 try:
35 try:
36 self.validate_repo(ui, sshcmd, args, remotecmd)
36 self.validate_repo(ui, sshcmd, args, remotecmd)
37 return # the repo is good, nothing more to do
38 except hg.RepoError:
37 except hg.RepoError:
39 pass
38 pass
39 else:
40 raise hg.RepoError(_("repository %s already exists") % path)
40
41
41 cmd = '%s %s "%s init %s"'
42 cmd = '%s %s "%s init %s"'
42 cmd = cmd % (sshcmd, args, remotecmd, self.path)
43 cmd = cmd % (sshcmd, args, remotecmd, self.path)
43
44
44 ui.note('running %s\n' % cmd)
45 ui.note('running %s\n' % cmd)
45 res = os.system(cmd)
46 res = os.system(cmd)
46 if res != 0:
47 if res != 0:
47 raise hg.RepoError(_("could not create remote repo"))
48 raise hg.RepoError(_("could not create remote repo"))
48
49
49 self.validate_repo(ui, sshcmd, args, remotecmd)
50 self.validate_repo(ui, sshcmd, args, remotecmd)
50
51
51 def url(self):
52 def url(self):
52 return self._url
53 return self._url
53
54
54 def validate_repo(self, ui, sshcmd, args, remotecmd):
55 def validate_repo(self, ui, sshcmd, args, remotecmd):
55 # cleanup up previous run
56 # cleanup up previous run
56 self.cleanup()
57 self.cleanup()
57
58
58 cmd = '%s %s "%s -R %s serve --stdio"'
59 cmd = '%s %s "%s -R %s serve --stdio"'
59 cmd = cmd % (sshcmd, args, remotecmd, self.path)
60 cmd = cmd % (sshcmd, args, remotecmd, self.path)
60
61
61 ui.note('running %s\n' % cmd)
62 ui.note('running %s\n' % cmd)
62 self.pipeo, self.pipei, self.pipee = os.popen3(cmd, 'b')
63 self.pipeo, self.pipei, self.pipee = os.popen3(cmd, 'b')
63
64
64 # skip any noise generated by remote shell
65 # skip any noise generated by remote shell
65 self.do_cmd("hello")
66 self.do_cmd("hello")
66 r = self.do_cmd("between", pairs=("%s-%s" % ("0"*40, "0"*40)))
67 r = self.do_cmd("between", pairs=("%s-%s" % ("0"*40, "0"*40)))
67 lines = ["", "dummy"]
68 lines = ["", "dummy"]
68 max_noise = 500
69 max_noise = 500
69 while lines[-1] and max_noise:
70 while lines[-1] and max_noise:
70 l = r.readline()
71 l = r.readline()
71 self.readerr()
72 self.readerr()
72 if lines[-1] == "1\n" and l == "\n":
73 if lines[-1] == "1\n" and l == "\n":
73 break
74 break
74 if l:
75 if l:
75 ui.debug(_("remote: "), l)
76 ui.debug(_("remote: "), l)
76 lines.append(l)
77 lines.append(l)
77 max_noise -= 1
78 max_noise -= 1
78 else:
79 else:
79 raise hg.RepoError(_("no response from remote hg"))
80 raise hg.RepoError(_("no response from remote hg"))
80
81
81 self.capabilities = ()
82 self.capabilities = ()
82 lines.reverse()
83 lines.reverse()
83 for l in lines:
84 for l in lines:
84 if l.startswith("capabilities:"):
85 if l.startswith("capabilities:"):
85 self.capabilities = l[:-1].split(":")[1].split()
86 self.capabilities = l[:-1].split(":")[1].split()
86 break
87 break
87
88
88 def readerr(self):
89 def readerr(self):
89 while 1:
90 while 1:
90 size = util.fstat(self.pipee).st_size
91 size = util.fstat(self.pipee).st_size
91 if size == 0: break
92 if size == 0: break
92 l = self.pipee.readline()
93 l = self.pipee.readline()
93 if not l: break
94 if not l: break
94 self.ui.status(_("remote: "), l)
95 self.ui.status(_("remote: "), l)
95
96
96 def cleanup(self):
97 def cleanup(self):
97 try:
98 try:
98 self.pipeo.close()
99 self.pipeo.close()
99 self.pipei.close()
100 self.pipei.close()
100 # read the error descriptor until EOF
101 # read the error descriptor until EOF
101 for l in self.pipee:
102 for l in self.pipee:
102 self.ui.status(_("remote: "), l)
103 self.ui.status(_("remote: "), l)
103 self.pipee.close()
104 self.pipee.close()
104 except:
105 except:
105 pass
106 pass
106
107
107 __del__ = cleanup
108 __del__ = cleanup
108
109
109 def do_cmd(self, cmd, **args):
110 def do_cmd(self, cmd, **args):
110 self.ui.debug(_("sending %s command\n") % cmd)
111 self.ui.debug(_("sending %s command\n") % cmd)
111 self.pipeo.write("%s\n" % cmd)
112 self.pipeo.write("%s\n" % cmd)
112 for k, v in args.items():
113 for k, v in args.items():
113 self.pipeo.write("%s %d\n" % (k, len(v)))
114 self.pipeo.write("%s %d\n" % (k, len(v)))
114 self.pipeo.write(v)
115 self.pipeo.write(v)
115 self.pipeo.flush()
116 self.pipeo.flush()
116
117
117 return self.pipei
118 return self.pipei
118
119
119 def call(self, cmd, **args):
120 def call(self, cmd, **args):
120 r = self.do_cmd(cmd, **args)
121 r = self.do_cmd(cmd, **args)
121 l = r.readline()
122 l = r.readline()
122 self.readerr()
123 self.readerr()
123 try:
124 try:
124 l = int(l)
125 l = int(l)
125 except:
126 except:
126 raise hg.RepoError(_("unexpected response '%s'") % l)
127 raise hg.RepoError(_("unexpected response '%s'") % l)
127 return r.read(l)
128 return r.read(l)
128
129
129 def lock(self):
130 def lock(self):
130 self.call("lock")
131 self.call("lock")
131 return remotelock(self)
132 return remotelock(self)
132
133
133 def unlock(self):
134 def unlock(self):
134 self.call("unlock")
135 self.call("unlock")
135
136
136 def heads(self):
137 def heads(self):
137 d = self.call("heads")
138 d = self.call("heads")
138 try:
139 try:
139 return map(bin, d[:-1].split(" "))
140 return map(bin, d[:-1].split(" "))
140 except:
141 except:
141 raise hg.RepoError(_("unexpected response '%s'") % (d[:400] + "..."))
142 raise hg.RepoError(_("unexpected response '%s'") % (d[:400] + "..."))
142
143
143 def branches(self, nodes):
144 def branches(self, nodes):
144 n = " ".join(map(hex, nodes))
145 n = " ".join(map(hex, nodes))
145 d = self.call("branches", nodes=n)
146 d = self.call("branches", nodes=n)
146 try:
147 try:
147 br = [ tuple(map(bin, b.split(" "))) for b in d.splitlines() ]
148 br = [ tuple(map(bin, b.split(" "))) for b in d.splitlines() ]
148 return br
149 return br
149 except:
150 except:
150 raise hg.RepoError(_("unexpected response '%s'") % (d[:400] + "..."))
151 raise hg.RepoError(_("unexpected response '%s'") % (d[:400] + "..."))
151
152
152 def between(self, pairs):
153 def between(self, pairs):
153 n = "\n".join(["-".join(map(hex, p)) for p in pairs])
154 n = "\n".join(["-".join(map(hex, p)) for p in pairs])
154 d = self.call("between", pairs=n)
155 d = self.call("between", pairs=n)
155 try:
156 try:
156 p = [ l and map(bin, l.split(" ")) or [] for l in d.splitlines() ]
157 p = [ l and map(bin, l.split(" ")) or [] for l in d.splitlines() ]
157 return p
158 return p
158 except:
159 except:
159 raise hg.RepoError(_("unexpected response '%s'") % (d[:400] + "..."))
160 raise hg.RepoError(_("unexpected response '%s'") % (d[:400] + "..."))
160
161
161 def changegroup(self, nodes, kind):
162 def changegroup(self, nodes, kind):
162 n = " ".join(map(hex, nodes))
163 n = " ".join(map(hex, nodes))
163 return self.do_cmd("changegroup", roots=n)
164 return self.do_cmd("changegroup", roots=n)
164
165
165 def unbundle(self, cg, heads, source):
166 def unbundle(self, cg, heads, source):
166 d = self.call("unbundle", heads=' '.join(map(hex, heads)))
167 d = self.call("unbundle", heads=' '.join(map(hex, heads)))
167 if d:
168 if d:
168 raise hg.RepoError(_("push refused: %s") % d)
169 raise hg.RepoError(_("push refused: %s") % d)
169
170
170 while 1:
171 while 1:
171 d = cg.read(4096)
172 d = cg.read(4096)
172 if not d: break
173 if not d: break
173 self.pipeo.write(str(len(d)) + '\n')
174 self.pipeo.write(str(len(d)) + '\n')
174 self.pipeo.write(d)
175 self.pipeo.write(d)
175 self.readerr()
176 self.readerr()
176
177
177 self.pipeo.write('0\n')
178 self.pipeo.write('0\n')
178 self.pipeo.flush()
179 self.pipeo.flush()
179
180
180 self.readerr()
181 self.readerr()
181 d = self.pipei.readline()
182 d = self.pipei.readline()
182 if d != '\n':
183 if d != '\n':
183 return 1
184 return 1
184
185
185 l = int(self.pipei.readline())
186 l = int(self.pipei.readline())
186 r = self.pipei.read(l)
187 r = self.pipei.read(l)
187 if not r:
188 if not r:
188 return 1
189 return 1
189 return int(r)
190 return int(r)
190
191
191 def addchangegroup(self, cg, source, url):
192 def addchangegroup(self, cg, source, url):
192 d = self.call("addchangegroup")
193 d = self.call("addchangegroup")
193 if d:
194 if d:
194 raise hg.RepoError(_("push refused: %s") % d)
195 raise hg.RepoError(_("push refused: %s") % d)
195 while 1:
196 while 1:
196 d = cg.read(4096)
197 d = cg.read(4096)
197 if not d: break
198 if not d: break
198 self.pipeo.write(d)
199 self.pipeo.write(d)
199 self.readerr()
200 self.readerr()
200
201
201 self.pipeo.flush()
202 self.pipeo.flush()
202
203
203 self.readerr()
204 self.readerr()
204 l = int(self.pipei.readline())
205 l = int(self.pipei.readline())
205 r = self.pipei.read(l)
206 r = self.pipei.read(l)
206 if not r:
207 if not r:
207 return 1
208 return 1
208 return int(r)
209 return int(r)
209
210
210 def stream_out(self):
211 def stream_out(self):
211 return self.do_cmd('stream_out')
212 return self.do_cmd('stream_out')
212
213
213 instance = sshrepository
214 instance = sshrepository
General Comments 0
You need to be logged in to leave comments. Login now