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