Mercurial > jhg
comparison src/org/tmatesoft/hg/repo/HgRemoteRepository.java @ 650:3b275cc2d2aa
Push: phase4 - settle local and remote phases, push updated phases regardless of server publishing state, do not push secret changesets
| author | Artem Tikhomirov <tikhomirov.artem@gmail.com> |
|---|---|
| date | Fri, 28 Jun 2013 19:27:26 +0200 |
| parents | e79cf9a8130b |
| children | 6e98d34eaca8 |
comparison
equal
deleted
inserted
replaced
| 649:e79cf9a8130b | 650:3b275cc2d2aa |
|---|---|
| 15 * contact TMate Software at support@hg4j.com | 15 * contact TMate Software at support@hg4j.com |
| 16 */ | 16 */ |
| 17 package org.tmatesoft.hg.repo; | 17 package org.tmatesoft.hg.repo; |
| 18 | 18 |
| 19 import static org.tmatesoft.hg.util.LogFacility.Severity.Info; | 19 import static org.tmatesoft.hg.util.LogFacility.Severity.Info; |
| 20 import static org.tmatesoft.hg.util.Outcome.Kind.Failure; | |
| 21 import static org.tmatesoft.hg.util.Outcome.Kind.Success; | |
| 20 | 22 |
| 21 import java.io.BufferedReader; | 23 import java.io.BufferedReader; |
| 22 import java.io.ByteArrayOutputStream; | 24 import java.io.ByteArrayOutputStream; |
| 23 import java.io.File; | 25 import java.io.File; |
| 24 import java.io.FileOutputStream; | 26 import java.io.FileOutputStream; |
| 60 import org.tmatesoft.hg.core.HgRemoteConnectionException; | 62 import org.tmatesoft.hg.core.HgRemoteConnectionException; |
| 61 import org.tmatesoft.hg.core.HgRepositoryNotFoundException; | 63 import org.tmatesoft.hg.core.HgRepositoryNotFoundException; |
| 62 import org.tmatesoft.hg.core.Nodeid; | 64 import org.tmatesoft.hg.core.Nodeid; |
| 63 import org.tmatesoft.hg.core.SessionContext; | 65 import org.tmatesoft.hg.core.SessionContext; |
| 64 import org.tmatesoft.hg.internal.DataSerializer; | 66 import org.tmatesoft.hg.internal.DataSerializer; |
| 67 import org.tmatesoft.hg.internal.DataSerializer.OutputStreamSerializer; | |
| 65 import org.tmatesoft.hg.internal.EncodingHelper; | 68 import org.tmatesoft.hg.internal.EncodingHelper; |
| 66 import org.tmatesoft.hg.internal.Internals; | 69 import org.tmatesoft.hg.internal.Internals; |
| 67 import org.tmatesoft.hg.internal.DataSerializer.OutputStreamSerializer; | |
| 68 import org.tmatesoft.hg.internal.PropertyMarshal; | 70 import org.tmatesoft.hg.internal.PropertyMarshal; |
| 71 import org.tmatesoft.hg.util.LogFacility.Severity; | |
| 69 import org.tmatesoft.hg.util.Outcome; | 72 import org.tmatesoft.hg.util.Outcome; |
| 70 import org.tmatesoft.hg.util.Pair; | 73 import org.tmatesoft.hg.util.Pair; |
| 71 import org.tmatesoft.hg.util.LogFacility.Severity; | |
| 72 import org.tmatesoft.hg.util.Outcome.Kind; | |
| 73 | 74 |
| 74 /** | 75 /** |
| 75 * WORK IN PROGRESS, DO NOT USE | 76 * WORK IN PROGRESS, DO NOT USE |
| 76 * | 77 * |
| 77 * @see http://mercurial.selenic.com/wiki/WireProtocol | 78 * @see http://mercurial.selenic.com/wiki/WireProtocol |
| 495 if (!remoteCapabilities.contains("pushkey")) { | 496 if (!remoteCapabilities.contains("pushkey")) { |
| 496 // old server defaults to publishing | 497 // old server defaults to publishing |
| 497 return new Phases(true, Collections.<Nodeid>emptyList()); | 498 return new Phases(true, Collections.<Nodeid>emptyList()); |
| 498 } | 499 } |
| 499 final List<Pair<String, String>> values = listkeys("phases", "Get remote phases"); | 500 final List<Pair<String, String>> values = listkeys("phases", "Get remote phases"); |
| 500 boolean publishing = true; | 501 boolean publishing = false; |
| 501 ArrayList<Nodeid> draftRoots = new ArrayList<Nodeid>(); | 502 ArrayList<Nodeid> draftRoots = new ArrayList<Nodeid>(); |
| 502 for (Pair<String, String> l : values) { | 503 for (Pair<String, String> l : values) { |
| 503 if ("publishing".equalsIgnoreCase(l.first())) { | 504 if ("publishing".equalsIgnoreCase(l.first())) { |
| 504 publishing = Boolean.parseBoolean(l.second()); | 505 publishing = Boolean.parseBoolean(l.second()); |
| 505 continue; | 506 continue; |
| 515 } | 516 } |
| 516 return new Phases(publishing, draftRoots); | 517 return new Phases(publishing, draftRoots); |
| 517 } | 518 } |
| 518 | 519 |
| 519 public Outcome updatePhase(HgPhase from, HgPhase to, Nodeid n) throws HgRemoteConnectionException, HgRuntimeException { | 520 public Outcome updatePhase(HgPhase from, HgPhase to, Nodeid n) throws HgRemoteConnectionException, HgRuntimeException { |
| 521 initCapabilities(); | |
| 522 if (!remoteCapabilities.contains("pushkey")) { | |
| 523 return new Outcome(Failure, "Server doesn't support pushkey protocol"); | |
| 524 } | |
| 520 if (pushkey("phases", n.toString(), String.valueOf(from.mercurialOrdinal()), String.valueOf(to.mercurialOrdinal()))) { | 525 if (pushkey("phases", n.toString(), String.valueOf(from.mercurialOrdinal()), String.valueOf(to.mercurialOrdinal()))) { |
| 521 return new Outcome(Kind.Success, String.format("Phase of %s updated to %s", n.shortNotation(), to.name())); | 526 return new Outcome(Success, String.format("Phase of %s updated to %s", n.shortNotation(), to.name())); |
| 522 } | 527 } |
| 523 return new Outcome(Kind.Failure, String.format("Phase update (%s: %s -> %s) failed", n.shortNotation(), from.name(), to.name())); | 528 return new Outcome(Failure, String.format("Phase update (%s: %s -> %s) failed", n.shortNotation(), from.name(), to.name())); |
| 524 } | 529 } |
| 525 | 530 |
| 526 | 531 |
| 527 public static void main(String[] args) throws Exception { | 532 public static void main(String[] args) throws Exception { |
| 528 final HgRemoteRepository r = new HgLookup().detectRemote("http://selenic.com/hg", null); | 533 final HgRemoteRepository r = new HgLookup().detectRemote("http://selenic.com/hg", null); |
| 630 } | 635 } |
| 631 | 636 |
| 632 private boolean pushkey(String namespace, String key, String oldValue, String newValue) throws HgRemoteConnectionException, HgRuntimeException { | 637 private boolean pushkey(String namespace, String key, String oldValue, String newValue) throws HgRemoteConnectionException, HgRuntimeException { |
| 633 HttpURLConnection c = null; | 638 HttpURLConnection c = null; |
| 634 try { | 639 try { |
| 635 final String p = String.format("%s?cmd=pushkey&namespace=%s&key=%s&old=%s&new=&s", url.getPath(), namespace, key, oldValue, newValue); | 640 final String p = String.format("%s?cmd=pushkey&namespace=%s&key=%s&old=%s&new=%s", url.getPath(), namespace, key, oldValue, newValue); |
| 636 URL u = new URL(url, p); | 641 URL u = new URL(url, p); |
| 637 c = setupConnection(u.openConnection()); | 642 c = setupConnection(u.openConnection()); |
| 643 c.setRequestMethod("POST"); | |
| 638 c.connect(); | 644 c.connect(); |
| 639 if (debug) { | 645 if (debug) { |
| 640 dumpResponseHeader(u, c); | 646 dumpResponseHeader(u, c); |
| 641 } | 647 } |
| 642 checkResponseOk(c, key, "pushkey"); | 648 checkResponseOk(c, key, "pushkey"); |
| 643 final InputStream is = c.getInputStream(); | 649 final InputStream is = c.getInputStream(); |
| 644 int rv = is.read(); | 650 int rv = is.read(); |
| 645 if (is.read() != -1) { | |
| 646 sessionContext.getLog().dump(getClass(), Severity.Error, "Unexpected data in response to pushkey"); | |
| 647 } | |
| 648 is.close(); | 651 is.close(); |
| 649 return rv == '1'; | 652 return rv == '1'; |
| 650 } catch (MalformedURLException ex) { | 653 } catch (MalformedURLException ex) { |
| 651 throw new HgRemoteConnectionException("Bad URL", ex).setRemoteCommand("pushkey").setServerInfo(getLocation()); | 654 throw new HgRemoteConnectionException("Bad URL", ex).setRemoteCommand("pushkey").setServerInfo(getLocation()); |
| 652 } catch (IOException ex) { | 655 } catch (IOException ex) { |
