Mercurial > jhg
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 } |
