Mercurial > hg4j
comparison src/org/tmatesoft/hg/repo/HgRemoteRepository.java @ 178:62665d8f0686
Complete logic to discover all branches missing locally. Most of wire protocol in HgRemoteRepository
| author | Artem Tikhomirov <tikhomirov.artem@gmail.com> |
|---|---|
| date | Wed, 06 Apr 2011 01:34:16 +0200 |
| parents | e10225daface |
| children | da426c2fe1ec |
comparison
equal
deleted
inserted
replaced
| 177:e10225daface | 178:62665d8f0686 |
|---|---|
| 25 import java.net.MalformedURLException; | 25 import java.net.MalformedURLException; |
| 26 import java.net.URL; | 26 import java.net.URL; |
| 27 import java.net.URLConnection; | 27 import java.net.URLConnection; |
| 28 import java.security.cert.CertificateException; | 28 import java.security.cert.CertificateException; |
| 29 import java.security.cert.X509Certificate; | 29 import java.security.cert.X509Certificate; |
| 30 import java.util.ArrayList; | |
| 30 import java.util.Collection; | 31 import java.util.Collection; |
| 31 import java.util.Collections; | 32 import java.util.Collections; |
| 32 import java.util.Iterator; | 33 import java.util.Iterator; |
| 33 import java.util.LinkedHashMap; | 34 import java.util.LinkedHashMap; |
| 34 import java.util.LinkedList; | 35 import java.util.LinkedList; |
| 57 public class HgRemoteRepository { | 58 public class HgRemoteRepository { |
| 58 | 59 |
| 59 private final URL url; | 60 private final URL url; |
| 60 private final SSLContext sslContext; | 61 private final SSLContext sslContext; |
| 61 private final String authInfo; | 62 private final String authInfo; |
| 63 private final boolean debug = Boolean.FALSE.booleanValue(); | |
| 62 | 64 |
| 63 HgRemoteRepository(URL url) throws HgException { | 65 HgRemoteRepository(URL url) throws HgException { |
| 64 if (url == null) { | 66 if (url == null) { |
| 65 throw new IllegalArgumentException(); | 67 throw new IllegalArgumentException(); |
| 66 } | 68 } |
| 102 } else { | 104 } else { |
| 103 authInfo = null; | 105 authInfo = null; |
| 104 } | 106 } |
| 105 } | 107 } |
| 106 | 108 |
| 107 public List<Nodeid> heads() { | 109 public List<Nodeid> heads() throws HgException { |
| 108 return Collections.singletonList(Nodeid.fromAscii("71ddbf8603e8e09d54ac9c5fe4bb5ae824589f1d")); | 110 try { |
| 109 // return Collections.emptyList(); | 111 URL u = new URL(url, url.getPath() + "?cmd=heads"); |
| 112 HttpURLConnection c = setupConnection(u.openConnection()); | |
| 113 c.connect(); | |
| 114 if (debug) { | |
| 115 dumpResponseHeader(u, c); | |
| 116 } | |
| 117 InputStreamReader is = new InputStreamReader(c.getInputStream(), "US-ASCII"); | |
| 118 StreamTokenizer st = new StreamTokenizer(is); | |
| 119 st.ordinaryChars('0', '9'); | |
| 120 st.wordChars('0', '9'); | |
| 121 st.eolIsSignificant(false); | |
| 122 LinkedList<Nodeid> parseResult = new LinkedList<Nodeid>(); | |
| 123 while (st.nextToken() != StreamTokenizer.TT_EOF) { | |
| 124 parseResult.add(Nodeid.fromAscii(st.sval)); | |
| 125 } | |
| 126 return parseResult; | |
| 127 } catch (MalformedURLException ex) { | |
| 128 throw new HgException(ex); | |
| 129 } catch (IOException ex) { | |
| 130 throw new HgException(ex); | |
| 131 } | |
| 110 } | 132 } |
| 111 | 133 |
| 112 public List<Nodeid> between(Nodeid tip, Nodeid base) throws HgException { | 134 public List<Nodeid> between(Nodeid tip, Nodeid base) throws HgException { |
| 113 Range r = new Range(base, tip); | 135 Range r = new Range(base, tip); |
| 114 // XXX shall handle errors like no range key in the returned map, not sure how. | 136 // XXX shall handle errors like no range key in the returned map, not sure how. |
| 153 os.flush(); | 175 os.flush(); |
| 154 os.close(); | 176 os.close(); |
| 155 } else { | 177 } else { |
| 156 c.connect(); | 178 c.connect(); |
| 157 } | 179 } |
| 158 System.out.printf("%d ranges, method:%s \n", ranges.size(), c.getRequestMethod()); | 180 if (debug) { |
| 159 System.out.printf("Query (%d bytes):%s\n", u.getQuery().length(), u.getQuery()); | 181 System.out.printf("%d ranges, method:%s \n", ranges.size(), c.getRequestMethod()); |
| 160 System.out.println("Response headers:"); | 182 dumpResponseHeader(u, c); |
| 161 final Map<String, List<String>> headerFields = c.getHeaderFields(); | |
| 162 for (String s : headerFields.keySet()) { | |
| 163 System.out.printf("%s: %s\n", s, c.getHeaderField(s)); | |
| 164 } | 183 } |
| 165 InputStreamReader is = new InputStreamReader(c.getInputStream(), "US-ASCII"); | 184 InputStreamReader is = new InputStreamReader(c.getInputStream(), "US-ASCII"); |
| 166 StreamTokenizer st = new StreamTokenizer(is); | 185 StreamTokenizer st = new StreamTokenizer(is); |
| 167 st.ordinaryChars('0', '9'); | 186 st.ordinaryChars('0', '9'); |
| 168 st.wordChars('0', '9'); | 187 st.wordChars('0', '9'); |
| 211 } catch (IOException ex) { | 230 } catch (IOException ex) { |
| 212 throw new HgException(ex); | 231 throw new HgException(ex); |
| 213 } | 232 } |
| 214 } | 233 } |
| 215 | 234 |
| 216 public List<RemoteBranch> branches(List<Nodeid> nodes) { | 235 public List<RemoteBranch> branches(List<Nodeid> nodes) throws HgException { |
| 217 return Collections.emptyList(); | 236 StringBuilder sb = new StringBuilder(20 + nodes.size() * 41); |
| 237 sb.append("nodes="); | |
| 238 for (Nodeid n : nodes) { | |
| 239 sb.append(n.toString()); | |
| 240 sb.append('+'); | |
| 241 } | |
| 242 if (sb.charAt(sb.length() - 1) == '+') { | |
| 243 // strip last space | |
| 244 sb.setLength(sb.length() - 1); | |
| 245 } | |
| 246 try { | |
| 247 URL u = new URL(url, url.getPath() + "?cmd=branches&" + sb.toString()); | |
| 248 HttpURLConnection c = setupConnection(u.openConnection()); | |
| 249 c.connect(); | |
| 250 if (debug) { | |
| 251 dumpResponseHeader(u, c); | |
| 252 } | |
| 253 InputStreamReader is = new InputStreamReader(c.getInputStream(), "US-ASCII"); | |
| 254 StreamTokenizer st = new StreamTokenizer(is); | |
| 255 st.ordinaryChars('0', '9'); | |
| 256 st.wordChars('0', '9'); | |
| 257 st.eolIsSignificant(false); | |
| 258 ArrayList<Nodeid> parseResult = new ArrayList<Nodeid>(nodes.size() * 4); | |
| 259 while (st.nextToken() != StreamTokenizer.TT_EOF) { | |
| 260 parseResult.add(Nodeid.fromAscii(st.sval)); | |
| 261 } | |
| 262 if (parseResult.size() != nodes.size() * 4) { | |
| 263 throw new HgException(String.format("Bad number of nodeids in result (shall be factor 4), expected %d, got %d", nodes.size()*4, parseResult.size())); | |
| 264 } | |
| 265 ArrayList<RemoteBranch> rv = new ArrayList<RemoteBranch>(nodes.size()); | |
| 266 for (int i = 0; i < nodes.size(); i++) { | |
| 267 RemoteBranch rb = new RemoteBranch(parseResult.get(i*4), parseResult.get(i*4 + 1), parseResult.get(i*4 + 2), parseResult.get(i*4 + 3)); | |
| 268 rv.add(rb); | |
| 269 } | |
| 270 return rv; | |
| 271 } catch (MalformedURLException ex) { | |
| 272 throw new HgException(ex); | |
| 273 } catch (IOException ex) { | |
| 274 throw new HgException(ex); | |
| 275 } | |
| 218 } | 276 } |
| 219 | 277 |
| 220 // WireProtocol wiki: roots = a list of the latest nodes on every service side changeset branch that both the client and server know about. | 278 // WireProtocol wiki: roots = a list of the latest nodes on every service side changeset branch that both the client and server know about. |
| 221 public HgBundle getChanges(List<Nodeid> roots) throws HgException { | 279 public HgBundle getChanges(List<Nodeid> roots) throws HgException { |
| 222 return new HgLookup().loadBundle(new File("/temp/hg/hg-bundle-000000000000-gz.tmp")); | 280 return new HgLookup().loadBundle(new File("/temp/hg/hg-bundle-000000000000-gz.tmp")); |
| 230 } | 288 } |
| 231 if (sslContext != null) { | 289 if (sslContext != null) { |
| 232 ((HttpsURLConnection) urlConnection).setSSLSocketFactory(sslContext.getSocketFactory()); | 290 ((HttpsURLConnection) urlConnection).setSSLSocketFactory(sslContext.getSocketFactory()); |
| 233 } | 291 } |
| 234 return (HttpURLConnection) urlConnection; | 292 return (HttpURLConnection) urlConnection; |
| 293 } | |
| 294 | |
| 295 private void dumpResponseHeader(URL u, HttpURLConnection c) { | |
| 296 System.out.printf("Query (%d bytes):%s\n", u.getQuery().length(), u.getQuery()); | |
| 297 System.out.println("Response headers:"); | |
| 298 final Map<String, List<String>> headerFields = c.getHeaderFields(); | |
| 299 for (String s : headerFields.keySet()) { | |
| 300 System.out.printf("%s: %s\n", s, c.getHeaderField(s)); | |
| 301 } | |
| 235 } | 302 } |
| 236 | 303 |
| 237 public static final class Range { | 304 public static final class Range { |
| 238 /** | 305 /** |
| 239 * Root of the range, earlier revision | 306 * Root of the range, earlier revision |
