Mercurial > hg4j
comparison src/org/tmatesoft/hg/internal/remote/SshConnector.java @ 697:24f4efedc9d5
Respect the fact ssh and http protocols use different compression approach to sent changegroup data
author | Artem Tikhomirov <tikhomirov.artem@gmail.com> |
---|---|
date | Tue, 06 Aug 2013 13:34:34 +0200 |
parents | 5b5d199e2eb3 |
children | 822f3a83ff57 |
comparison
equal
deleted
inserted
replaced
696:5b5d199e2eb3 | 697:24f4efedc9d5 |
---|---|
15 * contact TMate Software at support@hg4j.com | 15 * contact TMate Software at support@hg4j.com |
16 */ | 16 */ |
17 package org.tmatesoft.hg.internal.remote; | 17 package org.tmatesoft.hg.internal.remote; |
18 | 18 |
19 import java.io.BufferedReader; | 19 import java.io.BufferedReader; |
20 import java.io.ByteArrayInputStream; | |
20 import java.io.Closeable; | 21 import java.io.Closeable; |
21 import java.io.EOFException; | 22 import java.io.EOFException; |
22 import java.io.File; | 23 import java.io.File; |
23 import java.io.FilterInputStream; | 24 import java.io.FilterInputStream; |
24 import java.io.FilterOutputStream; | 25 import java.io.FilterOutputStream; |
25 import java.io.IOException; | 26 import java.io.IOException; |
26 import java.io.InputStream; | 27 import java.io.InputStream; |
27 import java.io.InputStreamReader; | 28 import java.io.InputStreamReader; |
28 import java.io.OutputStream; | 29 import java.io.OutputStream; |
30 import java.io.SequenceInputStream; | |
29 import java.net.URL; | 31 import java.net.URL; |
30 import java.util.ArrayList; | 32 import java.util.ArrayList; |
31 import java.util.Collection; | 33 import java.util.Collection; |
32 import java.util.Collections; | 34 import java.util.Collections; |
33 import java.util.List; | 35 import java.util.List; |
97 sessionUse++; | 99 sessionUse++; |
98 return; | 100 return; |
99 } | 101 } |
100 try { | 102 try { |
101 session = conn.openSession(); | 103 session = conn.openSession(); |
102 session.execCommand(String.format("hg -R %s serve --stdio", url.getPath())); | 104 final String path = url.getPath(); |
105 session.execCommand(String.format("hg -R %s serve --stdio", path.charAt(0) == '/' ? path.substring(1) : path)); | |
103 remoteErr = new StreamGobbler(session.getStderr()); | 106 remoteErr = new StreamGobbler(session.getStderr()); |
104 remoteOut = new StreamGobbler(session.getStdout()); | 107 remoteOut = new StreamGobbler(session.getStdout()); |
108 remoteIn = session.getStdin(); | |
105 sessionUse = 1; | 109 sessionUse = 1; |
106 } catch (IOException ex) { | 110 } catch (IOException ex) { |
107 throw new HgRemoteConnectionException("Failed to create ssh session", ex); | 111 throw new HgRemoteConnectionException("Failed to create ssh session", ex); |
108 } | 112 } |
109 } | 113 } |
117 } | 121 } |
118 forceSessionClose(); | 122 forceSessionClose(); |
119 } | 123 } |
120 | 124 |
121 public String getServerLocation() { | 125 public String getServerLocation() { |
122 return ""; // FIXME | 126 return url.toString(); // FIXME |
123 } | 127 } |
124 | 128 |
125 public String getCapabilities() throws HgRemoteConnectionException { | 129 public String getCapabilities() throws HgRemoteConnectionException { |
126 try { | 130 try { |
127 consume(remoteOut); | 131 consume(remoteOut); |
154 throw new HgRemoteConnectionException("Failed to initiate dialog with server", ex).setRemoteCommand(CMD_HELLO).setServerInfo(getServerLocation()); | 158 throw new HgRemoteConnectionException("Failed to initiate dialog with server", ex).setRemoteCommand(CMD_HELLO).setServerInfo(getServerLocation()); |
155 } | 159 } |
156 } | 160 } |
157 | 161 |
158 public InputStream heads() throws HgRemoteConnectionException { | 162 public InputStream heads() throws HgRemoteConnectionException { |
159 return executeCommand("heads", Collections.<Parameter>emptyList()); | 163 return executeCommand("heads", Collections.<Parameter>emptyList(), true); |
160 } | 164 } |
161 | 165 |
162 public InputStream between(Collection<Range> ranges) throws HgRemoteConnectionException { | 166 public InputStream between(Collection<Range> ranges) throws HgRemoteConnectionException { |
163 StringBuilder sb = new StringBuilder(ranges.size() * 82); | 167 StringBuilder sb = new StringBuilder(ranges.size() * 82); |
164 for (Range r : ranges) { | 168 for (Range r : ranges) { |
165 r.append(sb).append(' '); | 169 r.append(sb).append(' '); |
166 } | 170 } |
167 if (!ranges.isEmpty()) { | 171 if (!ranges.isEmpty()) { |
168 sb.setLength(sb.length() - 1); | 172 sb.setLength(sb.length() - 1); |
169 } | 173 } |
170 return executeCommand("between", Collections.singletonList(new Parameter("pairs", sb.toString()))); | 174 return executeCommand("between", Collections.singletonList(new Parameter("pairs", sb.toString())), true); |
171 } | 175 } |
172 | 176 |
173 public InputStream branches(List<Nodeid> nodes) throws HgRemoteConnectionException { | 177 public InputStream branches(List<Nodeid> nodes) throws HgRemoteConnectionException { |
174 String l = join(nodes, ' '); | 178 String l = join(nodes, ' '); |
175 return executeCommand("branches", Collections.singletonList(new Parameter("nodes", l))); | 179 return executeCommand("branches", Collections.singletonList(new Parameter("nodes", l)), true); |
176 } | 180 } |
177 | 181 |
178 public InputStream changegroup(List<Nodeid> roots) throws HgRemoteConnectionException, HgRuntimeException { | 182 public InputStream changegroup(List<Nodeid> roots) throws HgRemoteConnectionException, HgRuntimeException { |
179 String l = join(roots, ' '); | 183 String l = join(roots, ' '); |
180 return executeCommand("changegroup", Collections.singletonList(new Parameter("roots", l))); | 184 InputStream cg = executeCommand("changegroup", Collections.singletonList(new Parameter("roots", l)), false); |
185 InputStream prefix = new ByteArrayInputStream("HG10UN".getBytes()); | |
186 return new SequenceInputStream(prefix, cg); | |
181 } | 187 } |
182 | 188 |
183 public OutputStream unbundle(long outputLen, List<Nodeid> remoteHeads) throws HgRemoteConnectionException, HgRuntimeException { | 189 public OutputStream unbundle(long outputLen, List<Nodeid> remoteHeads) throws HgRemoteConnectionException, HgRuntimeException { |
184 String l = join(remoteHeads, ' '); | 190 String l = join(remoteHeads, ' '); |
185 try { | 191 try { |
208 ArrayList<Parameter> p = new ArrayList<Parameter>(); | 214 ArrayList<Parameter> p = new ArrayList<Parameter>(); |
209 p.add(new Parameter("namespace", namespace)); | 215 p.add(new Parameter("namespace", namespace)); |
210 p.add(new Parameter("key", key)); | 216 p.add(new Parameter("key", key)); |
211 p.add(new Parameter("old", oldValue)); | 217 p.add(new Parameter("old", oldValue)); |
212 p.add(new Parameter("new", newValue)); | 218 p.add(new Parameter("new", newValue)); |
213 return executeCommand("pushkey", p); | 219 return executeCommand("pushkey", p, true); |
214 } | 220 } |
215 | 221 |
216 public InputStream listkeys(String namespace, String actionName) throws HgRemoteConnectionException, HgRuntimeException { | 222 public InputStream listkeys(String namespace, String actionName) throws HgRemoteConnectionException, HgRuntimeException { |
217 return executeCommand("listkeys", Collections.singletonList(new Parameter("namespace", namespace))); | 223 return executeCommand("listkeys", Collections.singletonList(new Parameter("namespace", namespace)), true); |
218 } | 224 } |
219 | 225 |
220 private InputStream executeCommand(String cmd, List<Parameter> parameters) throws HgRemoteConnectionException { | 226 private InputStream executeCommand(String cmd, List<Parameter> parameters, boolean expectResponseLength) throws HgRemoteConnectionException { |
221 try { | 227 try { |
222 consume(remoteOut); | 228 consume(remoteOut); |
223 consume(remoteErr); | 229 consume(remoteErr); |
224 remoteIn.write(cmd.getBytes()); | 230 remoteIn.write(cmd.getBytes()); |
225 remoteIn.write('\n'); | 231 remoteIn.write('\n'); |
226 writeParameters(parameters); | 232 writeParameters(parameters); |
227 checkError(); | 233 checkError(); |
228 int responseLen = readResponseLength(); | 234 if (expectResponseLength) { |
229 checkError(); | 235 int responseLen = readResponseLength(); |
230 return new FilterStream(remoteOut, responseLen); | 236 checkError(); |
237 return new FilterStream(remoteOut, responseLen); | |
238 } else { | |
239 return new FilterStream(remoteOut, Integer.MAX_VALUE); | |
240 } | |
231 } catch (IOException ex) { | 241 } catch (IOException ex) { |
232 throw new HgRemoteConnectionException("Communication failure", ex).setRemoteCommand(cmd).setServerInfo(getServerLocation()); | 242 throw new HgRemoteConnectionException("Communication failure", ex).setRemoteCommand(cmd).setServerInfo(getServerLocation()); |
233 } | 243 } |
234 } | 244 } |
235 | 245 |
374 } | 384 } |
375 return r; | 385 return r; |
376 } | 386 } |
377 @Override | 387 @Override |
378 public void close() throws IOException { | 388 public void close() throws IOException { |
389 length = 0; | |
379 // INTENTIONALLY DOES NOT CLOSE THE STREAM | 390 // INTENTIONALLY DOES NOT CLOSE THE STREAM |
380 } | 391 } |
381 } | 392 } |
382 } | 393 } |