diff src/org/tmatesoft/hg/core/HgPushCommand.java @ 652:cd77bf51b562

Push: tests. Commit respects phases.new-commit setting. Fix outgoing when changes are not children of common (Issue 47)
author Artem Tikhomirov <tikhomirov.artem@gmail.com>
date Tue, 02 Jul 2013 23:21:16 +0200
parents 3b275cc2d2aa
children 629a7370554c
line wrap: on
line diff
--- a/src/org/tmatesoft/hg/core/HgPushCommand.java	Mon Jul 01 21:19:53 2013 +0200
+++ b/src/org/tmatesoft/hg/core/HgPushCommand.java	Tue Jul 02 23:21:16 2013 +0200
@@ -102,7 +102,7 @@
 				RevisionSet presentDraft = phaseHelper.allDraft();
 				RevisionSet secretLeft, draftLeft;
 				HgRemoteRepository.Phases remotePhases = remoteRepo.getPhases();
-				RevisionSet remoteDrafts = knownRemoteDrafts(remotePhases, parentHelper, outgoing);
+				RevisionSet remoteDrafts = knownRemoteDrafts(remotePhases, parentHelper, outgoing, presentSecret);
 				if (remotePhases.isPublishingServer()) {
 					// although it's unlikely outgoing would affect secret changesets,
 					// it doesn't hurt to check secret roots along with draft ones
@@ -136,9 +136,15 @@
 					 * Local draft roots shall be updated
 					 */
 					RevisionSet sharedDraft = presentDraft.intersect(remoteDrafts); // (I: ~presentDraft; II: ~remoteDraft
+					// XXX do I really need sharedDrafts here? why not ancestors(remoteDrafts)?
 					RevisionSet localDraftRemotePublic = presentDraft.ancestors(sharedDraft, parentHelper); // I: 0; II: those treated public on remote
+					// remoteDrafts are local revisions known as draft@remote
+					// remoteDraftsLocalPublic - revisions that would cease to be listed as draft on remote
+					RevisionSet remoteDraftsLocalPublic = remoteDrafts.ancestors(sharedDraft, parentHelper);
+					RevisionSet remoteDraftsLeft = remoteDrafts.subtract(remoteDraftsLocalPublic);
 					// forget those deemed public by remote (drafts shared by both remote and local are ok to stay)
-					draftLeft = presentDraft.subtract(localDraftRemotePublic);
+					RevisionSet combinedDraft = presentDraft.union(remoteDraftsLeft);
+					draftLeft = combinedDraft.subtract(localDraftRemotePublic);
 				}
 				final RevisionSet newDraftRoots = draftLeft.roots(parentHelper);
 				final RevisionSet newSecretRoots = secretLeft.roots(parentHelper);
@@ -192,7 +198,7 @@
 		}
 	}
 	
-	private RevisionSet knownRemoteDrafts(HgRemoteRepository.Phases remotePhases, HgParentChildMap<HgChangelog> parentHelper, RevisionSet outgoing) {
+	private RevisionSet knownRemoteDrafts(HgRemoteRepository.Phases remotePhases, HgParentChildMap<HgChangelog> parentHelper, RevisionSet outgoing, RevisionSet localSecret) {
 		ArrayList<Nodeid> knownRemoteDraftRoots = new ArrayList<Nodeid>();
 		for (Nodeid rdr : remotePhases.draftRoots()) {
 			if (parentHelper.knownNode(rdr)) {
@@ -201,7 +207,11 @@
 		}
 		// knownRemoteDraftRoots + childrenOf(knownRemoteDraftRoots) is everything remote may treat as Draft
 		RevisionSet remoteDrafts = new RevisionSet(knownRemoteDraftRoots);
-		remoteDrafts = remoteDrafts.union(remoteDrafts.children(parentHelper));
+		RevisionSet localChildren = remoteDrafts.children(parentHelper);
+		// we didn't send any local secret revision
+		localChildren = localChildren.subtract(localSecret);
+		// draft roots are among remote drafts
+		remoteDrafts = remoteDrafts.union(localChildren);
 		// 1) outgoing.children gives all local revisions accessible from outgoing.
 		// 2) outgoing.roots.children is equivalent with smaller intermediate set, the way we build
 		// childrenOf doesn't really benefits from that.