comparison src/org/tmatesoft/hg/core/HgPushCommand.java @ 663:46b56864b483

Pull: phase2 - update phases from remote, fncache with added files. Tests
author Artem Tikhomirov <tikhomirov.artem@gmail.com>
date Wed, 10 Jul 2013 16:41:49 +0200
parents 12a4f60ea972
children ae2d439fbed3
comparison
equal deleted inserted replaced
662:af5223b86dd3 663:46b56864b483
16 */ 16 */
17 package org.tmatesoft.hg.core; 17 package org.tmatesoft.hg.core;
18 18
19 import java.io.File; 19 import java.io.File;
20 import java.io.IOException; 20 import java.io.IOException;
21 import java.util.ArrayList;
22 import java.util.Collection; 21 import java.util.Collection;
23 import java.util.Collections; 22 import java.util.Collections;
24 import java.util.List; 23 import java.util.List;
25 24
26 import org.tmatesoft.hg.internal.BundleGenerator; 25 import org.tmatesoft.hg.internal.BundleGenerator;
97 remoteRepo.unbundle(b, comparator.getRemoteHeads()); 96 remoteRepo.unbundle(b, comparator.getRemoteHeads());
98 progress.worked(20); 97 progress.worked(20);
99 // 98 //
100 // update phase information 99 // update phase information
101 if (phaseHelper.isCapableOfPhases()) { 100 if (phaseHelper.isCapableOfPhases()) {
102 RevisionSet presentSecret = phaseHelper.allSecret();
103 RevisionSet presentDraft = phaseHelper.allDraft();
104 RevisionSet secretLeft, draftLeft;
105 HgRemoteRepository.Phases remotePhases = remoteRepo.getPhases(); 101 HgRemoteRepository.Phases remotePhases = remoteRepo.getPhases();
106 RevisionSet remoteDrafts = knownRemoteDrafts(remotePhases, parentHelper, outgoing, presentSecret); 102 RevisionSet remoteDraftsLocalPublic = phaseHelper.synchronizeWithRemote(remotePhases, outgoing);
107 if (remotePhases.isPublishingServer()) {
108 // although it's unlikely outgoing would affect secret changesets,
109 // it doesn't hurt to check secret roots along with draft ones
110 secretLeft = presentSecret.subtract(outgoing);
111 draftLeft = presentDraft.subtract(outgoing);
112 } else {
113 // shall merge local and remote phase states
114 // revisions that cease to be secret (gonna become Public), e.g. someone else pushed them
115 RevisionSet secretGone = presentSecret.intersect(remoteDrafts);
116 // parents of those remote drafts are public, mark them as public locally, too
117 RevisionSet remotePublic = presentSecret.ancestors(secretGone, parentHelper);
118 secretLeft = presentSecret.subtract(secretGone).subtract(remotePublic);
119 /*
120 * Revisions grow from left to right (parents to the left, children to the right)
121 *
122 * I: Set of local is subset of remote
123 *
124 * local draft
125 * --o---r---o---l---o--
126 * remote draft
127 *
128 * Remote draft roots shall be updated
129 *
130 *
131 * II: Set of local is superset of remote
132 *
133 * local draft
134 * --o---l---o---r---o--
135 * remote draft
136 *
137 * Local draft roots shall be updated
138 */
139 RevisionSet sharedDraft = presentDraft.intersect(remoteDrafts); // (I: ~presentDraft; II: ~remoteDraft
140 // XXX do I really need sharedDrafts here? why not ancestors(remoteDrafts)?
141 RevisionSet localDraftRemotePublic = presentDraft.ancestors(sharedDraft, parentHelper); // I: 0; II: those treated public on remote
142 // remoteDrafts are local revisions known as draft@remote
143 // remoteDraftsLocalPublic - revisions that would cease to be listed as draft on remote
144 RevisionSet remoteDraftsLocalPublic = remoteDrafts.ancestors(sharedDraft, parentHelper);
145 RevisionSet remoteDraftsLeft = remoteDrafts.subtract(remoteDraftsLocalPublic);
146 // forget those deemed public by remote (drafts shared by both remote and local are ok to stay)
147 RevisionSet combinedDraft = presentDraft.union(remoteDraftsLeft);
148 draftLeft = combinedDraft.subtract(localDraftRemotePublic);
149 }
150 final RevisionSet newDraftRoots = draftLeft.roots(parentHelper);
151 final RevisionSet newSecretRoots = secretLeft.roots(parentHelper);
152 phaseHelper.updateRoots(newDraftRoots.asList(), newSecretRoots.asList());
153 //
154 // if there's a remote draft root that points to revision we know is public
155 RevisionSet remoteDraftsLocalPublic = remoteDrafts.subtract(draftLeft).subtract(secretLeft);
156 if (!remoteDraftsLocalPublic.isEmpty()) { 103 if (!remoteDraftsLocalPublic.isEmpty()) {
157 // foreach remoteDraftsLocallyPublic.heads() do push Draft->Public 104 // foreach remoteDraftsLocallyPublic.heads() do push Draft->Public
158 for (Nodeid n : remoteDraftsLocalPublic.heads(parentHelper)) { 105 for (Nodeid n : remoteDraftsLocalPublic.heads(parentHelper)) {
159 try { 106 try {
160 Outcome upo = remoteRepo.updatePhase(HgPhase.Draft, HgPhase.Public, n); 107 Outcome upo = remoteRepo.updatePhase(HgPhase.Draft, HgPhase.Public, n);
200 } 147 }
201 148
202 public Collection<Nodeid> getPushedRevisions() { 149 public Collection<Nodeid> getPushedRevisions() {
203 return outgoing == null ? Collections.<Nodeid>emptyList() : outgoing.asList(); 150 return outgoing == null ? Collections.<Nodeid>emptyList() : outgoing.asList();
204 } 151 }
205
206 private RevisionSet knownRemoteDrafts(HgRemoteRepository.Phases remotePhases, HgParentChildMap<HgChangelog> parentHelper, RevisionSet outgoing, RevisionSet localSecret) {
207 ArrayList<Nodeid> knownRemoteDraftRoots = new ArrayList<Nodeid>();
208 for (Nodeid rdr : remotePhases.draftRoots()) {
209 if (parentHelper.knownNode(rdr)) {
210 knownRemoteDraftRoots.add(rdr);
211 }
212 }
213 // knownRemoteDraftRoots + childrenOf(knownRemoteDraftRoots) is everything remote may treat as Draft
214 RevisionSet remoteDrafts = new RevisionSet(knownRemoteDraftRoots);
215 RevisionSet localChildren = remoteDrafts.children(parentHelper);
216 // we didn't send any local secret revision
217 localChildren = localChildren.subtract(localSecret);
218 // draft roots are among remote drafts
219 remoteDrafts = remoteDrafts.union(localChildren);
220 // 1) outgoing.children gives all local revisions accessible from outgoing.
221 // 2) outgoing.roots.children is equivalent with smaller intermediate set, the way we build
222 // childrenOf doesn't really benefits from that.
223 RevisionSet localChildrenNotSent = outgoing.children(parentHelper).subtract(outgoing);
224 // remote shall know only what we've sent, subtract revisions we didn't actually sent
225 remoteDrafts = remoteDrafts.subtract(localChildrenNotSent);
226 return remoteDrafts;
227 }
228 } 152 }