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 }