Mercurial > jhg
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 } |