Mercurial > jhg
comparison src/org/tmatesoft/hg/repo/HgRemoteRepository.java @ 215:41a778e3fd31
Issue 5: Facilities for progress and cancellation. More specific exceptions. Exceptions from callbacks as RuntimeException
| author | Artem Tikhomirov <tikhomirov.artem@gmail.com> |
|---|---|
| date | Tue, 17 May 2011 00:56:54 +0200 |
| parents | 6a2481866491 |
| children | 9fb50c04f03c |
comparison
equal
deleted
inserted
replaced
| 214:4252faa556cd | 215:41a778e3fd31 |
|---|---|
| 46 import javax.net.ssl.TrustManager; | 46 import javax.net.ssl.TrustManager; |
| 47 import javax.net.ssl.X509TrustManager; | 47 import javax.net.ssl.X509TrustManager; |
| 48 | 48 |
| 49 import org.tmatesoft.hg.core.HgBadArgumentException; | 49 import org.tmatesoft.hg.core.HgBadArgumentException; |
| 50 import org.tmatesoft.hg.core.HgBadStateException; | 50 import org.tmatesoft.hg.core.HgBadStateException; |
| 51 import org.tmatesoft.hg.core.HgException; | 51 import org.tmatesoft.hg.core.HgRemoteConnectionException; |
| 52 import org.tmatesoft.hg.core.Nodeid; | 52 import org.tmatesoft.hg.core.Nodeid; |
| 53 | 53 |
| 54 /** | 54 /** |
| 55 * WORK IN PROGRESS, DO NOT USE | 55 * WORK IN PROGRESS, DO NOT USE |
| 56 * | 56 * |
| 113 } else { | 113 } else { |
| 114 authInfo = null; | 114 authInfo = null; |
| 115 } | 115 } |
| 116 } | 116 } |
| 117 | 117 |
| 118 public boolean isInvalid() throws HgException { | 118 public boolean isInvalid() throws HgRemoteConnectionException { |
| 119 // say hello to server, check response | 119 // say hello to server, check response |
| 120 if (Boolean.FALSE.booleanValue()) { | 120 if (Boolean.FALSE.booleanValue()) { |
| 121 throw HgRepository.notImplemented(); | 121 throw HgRepository.notImplemented(); |
| 122 } | 122 } |
| 123 return false; // FIXME | 123 return false; // FIXME |
| 135 } else { | 135 } else { |
| 136 return String.format("%s://%s%s", url.getProtocol(), url.getHost(), url.getPath()); | 136 return String.format("%s://%s%s", url.getProtocol(), url.getHost(), url.getPath()); |
| 137 } | 137 } |
| 138 } | 138 } |
| 139 | 139 |
| 140 public List<Nodeid> heads() throws HgException { | 140 public List<Nodeid> heads() throws HgRemoteConnectionException { |
| 141 try { | 141 try { |
| 142 URL u = new URL(url, url.getPath() + "?cmd=heads"); | 142 URL u = new URL(url, url.getPath() + "?cmd=heads"); |
| 143 HttpURLConnection c = setupConnection(u.openConnection()); | 143 HttpURLConnection c = setupConnection(u.openConnection()); |
| 144 c.connect(); | 144 c.connect(); |
| 145 if (debug) { | 145 if (debug) { |
| 154 while (st.nextToken() != StreamTokenizer.TT_EOF) { | 154 while (st.nextToken() != StreamTokenizer.TT_EOF) { |
| 155 parseResult.add(Nodeid.fromAscii(st.sval)); | 155 parseResult.add(Nodeid.fromAscii(st.sval)); |
| 156 } | 156 } |
| 157 return parseResult; | 157 return parseResult; |
| 158 } catch (MalformedURLException ex) { | 158 } catch (MalformedURLException ex) { |
| 159 throw new HgException(ex); | 159 throw new HgRemoteConnectionException("Bad URL", ex).setRemoteCommand("heads").setServerInfo(getLocation()); |
| 160 } catch (IOException ex) { | 160 } catch (IOException ex) { |
| 161 throw new HgException(ex); | 161 throw new HgRemoteConnectionException("Communication failure", ex).setRemoteCommand("heads").setServerInfo(getLocation()); |
| 162 } | 162 } |
| 163 } | 163 } |
| 164 | 164 |
| 165 public List<Nodeid> between(Nodeid tip, Nodeid base) throws HgException { | 165 public List<Nodeid> between(Nodeid tip, Nodeid base) throws HgRemoteConnectionException { |
| 166 Range r = new Range(base, tip); | 166 Range r = new Range(base, tip); |
| 167 // XXX shall handle errors like no range key in the returned map, not sure how. | 167 // XXX shall handle errors like no range key in the returned map, not sure how. |
| 168 return between(Collections.singletonList(r)).get(r); | 168 return between(Collections.singletonList(r)).get(r); |
| 169 } | 169 } |
| 170 | 170 |
| 171 /** | 171 /** |
| 172 * @param ranges | 172 * @param ranges |
| 173 * @return map, where keys are input instances, values are corresponding server reply | 173 * @return map, where keys are input instances, values are corresponding server reply |
| 174 * @throws HgException | 174 * @throws HgRemoteConnectionException |
| 175 */ | 175 */ |
| 176 public Map<Range, List<Nodeid>> between(Collection<Range> ranges) throws HgException { | 176 public Map<Range, List<Nodeid>> between(Collection<Range> ranges) throws HgRemoteConnectionException { |
| 177 if (ranges.isEmpty()) { | 177 if (ranges.isEmpty()) { |
| 178 return Collections.emptyMap(); | 178 return Collections.emptyMap(); |
| 179 } | 179 } |
| 180 // if fact, shall do other way round, this method shall send | 180 // if fact, shall do other way round, this method shall send |
| 181 LinkedHashMap<Range, List<Nodeid>> rv = new LinkedHashMap<HgRemoteRepository.Range, List<Nodeid>>(ranges.size() * 4 / 3); | 181 LinkedHashMap<Range, List<Nodeid>> rv = new LinkedHashMap<HgRemoteRepository.Range, List<Nodeid>>(ranges.size() * 4 / 3); |
| 255 } | 255 } |
| 256 } | 256 } |
| 257 is.close(); | 257 is.close(); |
| 258 return rv; | 258 return rv; |
| 259 } catch (MalformedURLException ex) { | 259 } catch (MalformedURLException ex) { |
| 260 throw new HgException(ex); | 260 throw new HgRemoteConnectionException("Bad URL", ex).setRemoteCommand("between").setServerInfo(getLocation()); |
| 261 } catch (IOException ex) { | 261 } catch (IOException ex) { |
| 262 throw new HgException(ex); | 262 throw new HgRemoteConnectionException("Communication failure", ex).setRemoteCommand("between").setServerInfo(getLocation()); |
| 263 } | 263 } |
| 264 } | 264 } |
| 265 | 265 |
| 266 public List<RemoteBranch> branches(List<Nodeid> nodes) throws HgException { | 266 public List<RemoteBranch> branches(List<Nodeid> nodes) throws HgRemoteConnectionException { |
| 267 StringBuilder sb = new StringBuilder(20 + nodes.size() * 41); | 267 StringBuilder sb = new StringBuilder(20 + nodes.size() * 41); |
| 268 sb.append("nodes="); | 268 sb.append("nodes="); |
| 269 for (Nodeid n : nodes) { | 269 for (Nodeid n : nodes) { |
| 270 sb.append(n.toString()); | 270 sb.append(n.toString()); |
| 271 sb.append('+'); | 271 sb.append('+'); |
| 289 ArrayList<Nodeid> parseResult = new ArrayList<Nodeid>(nodes.size() * 4); | 289 ArrayList<Nodeid> parseResult = new ArrayList<Nodeid>(nodes.size() * 4); |
| 290 while (st.nextToken() != StreamTokenizer.TT_EOF) { | 290 while (st.nextToken() != StreamTokenizer.TT_EOF) { |
| 291 parseResult.add(Nodeid.fromAscii(st.sval)); | 291 parseResult.add(Nodeid.fromAscii(st.sval)); |
| 292 } | 292 } |
| 293 if (parseResult.size() != nodes.size() * 4) { | 293 if (parseResult.size() != nodes.size() * 4) { |
| 294 throw new HgException(String.format("Bad number of nodeids in result (shall be factor 4), expected %d, got %d", nodes.size()*4, parseResult.size())); | 294 throw new HgRemoteConnectionException(String.format("Bad number of nodeids in result (shall be factor 4), expected %d, got %d", nodes.size()*4, parseResult.size())); |
| 295 } | 295 } |
| 296 ArrayList<RemoteBranch> rv = new ArrayList<RemoteBranch>(nodes.size()); | 296 ArrayList<RemoteBranch> rv = new ArrayList<RemoteBranch>(nodes.size()); |
| 297 for (int i = 0; i < nodes.size(); i++) { | 297 for (int i = 0; i < nodes.size(); i++) { |
| 298 RemoteBranch rb = new RemoteBranch(parseResult.get(i*4), parseResult.get(i*4 + 1), parseResult.get(i*4 + 2), parseResult.get(i*4 + 3)); | 298 RemoteBranch rb = new RemoteBranch(parseResult.get(i*4), parseResult.get(i*4 + 1), parseResult.get(i*4 + 2), parseResult.get(i*4 + 3)); |
| 299 rv.add(rb); | 299 rv.add(rb); |
| 300 } | 300 } |
| 301 return rv; | 301 return rv; |
| 302 } catch (MalformedURLException ex) { | 302 } catch (MalformedURLException ex) { |
| 303 throw new HgException(ex); | 303 throw new HgRemoteConnectionException("Bad URL", ex).setRemoteCommand("branches").setServerInfo(getLocation()); |
| 304 } catch (IOException ex) { | 304 } catch (IOException ex) { |
| 305 throw new HgException(ex); | 305 throw new HgRemoteConnectionException("Communication failure", ex).setRemoteCommand("branches").setServerInfo(getLocation()); |
| 306 } | 306 } |
| 307 } | 307 } |
| 308 | 308 |
| 309 /* | 309 /* |
| 310 * XXX need to describe behavior when roots arg is empty; our RepositoryComparator code currently returns empty lists when | 310 * XXX need to describe behavior when roots arg is empty; our RepositoryComparator code currently returns empty lists when |
| 320 * | 320 * |
| 321 * according to latter, bundleformat data is sent through zlib | 321 * according to latter, bundleformat data is sent through zlib |
| 322 * (there's no header like HG10?? with the server output, though, | 322 * (there's no header like HG10?? with the server output, though, |
| 323 * as one may expect according to http://mercurial.selenic.com/wiki/BundleFormat) | 323 * as one may expect according to http://mercurial.selenic.com/wiki/BundleFormat) |
| 324 */ | 324 */ |
| 325 public HgBundle getChanges(List<Nodeid> roots) throws HgException { | 325 public HgBundle getChanges(List<Nodeid> roots) throws HgRemoteConnectionException { |
| 326 List<Nodeid> _roots = roots.isEmpty() ? Collections.singletonList(Nodeid.NULL) : roots; | 326 List<Nodeid> _roots = roots.isEmpty() ? Collections.singletonList(Nodeid.NULL) : roots; |
| 327 StringBuilder sb = new StringBuilder(20 + _roots.size() * 41); | 327 StringBuilder sb = new StringBuilder(20 + _roots.size() * 41); |
| 328 sb.append("roots="); | 328 sb.append("roots="); |
| 329 for (Nodeid n : _roots) { | 329 for (Nodeid n : _roots) { |
| 330 sb.append(n.toString()); | 330 sb.append(n.toString()); |
| 344 File tf = writeBundle(c.getInputStream(), false, "HG10GZ" /*didn't see any other that zip*/); | 344 File tf = writeBundle(c.getInputStream(), false, "HG10GZ" /*didn't see any other that zip*/); |
| 345 if (debug) { | 345 if (debug) { |
| 346 System.out.printf("Wrote bundle %s for roots %s\n", tf, sb); | 346 System.out.printf("Wrote bundle %s for roots %s\n", tf, sb); |
| 347 } | 347 } |
| 348 return getLookupHelper().loadBundle(tf); | 348 return getLookupHelper().loadBundle(tf); |
| 349 } catch (MalformedURLException ex) { | 349 } catch (MalformedURLException ex) { // XXX in fact, this exception might be better to be re-thrown as RuntimeEx, |
| 350 throw new HgException(ex); | 350 // as there's little user can do about this issue (URLs are constructed by our code) |
| 351 throw new HgRemoteConnectionException("Bad URL", ex).setRemoteCommand("changegroup").setServerInfo(getLocation()); | |
| 351 } catch (IOException ex) { | 352 } catch (IOException ex) { |
| 352 throw new HgException(ex); | 353 throw new HgRemoteConnectionException("Communication failure", ex).setRemoteCommand("changegroup").setServerInfo(getLocation()); |
| 353 } | 354 } |
| 354 } | 355 } |
| 355 | 356 |
| 356 @Override | 357 @Override |
| 357 public String toString() { | 358 public String toString() { |
