Mercurial > jhg
comparison src/org/tmatesoft/hg/core/HgPushCommand.java @ 649:e79cf9a8130b
Push: phase4 - update local and remote phase information
author | Artem Tikhomirov <tikhomirov.artem@gmail.com> |
---|---|
date | Wed, 26 Jun 2013 20:52:38 +0200 |
parents | 3b7d51ed4c65 |
children | 3b275cc2d2aa |
comparison
equal
deleted
inserted
replaced
648:690e71d29bf6 | 649:e79cf9a8130b |
---|---|
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.net.URL; | 21 import java.net.URL; |
22 import java.util.ArrayList; | |
22 import java.util.List; | 23 import java.util.List; |
23 | 24 |
24 import org.tmatesoft.hg.internal.BundleGenerator; | 25 import org.tmatesoft.hg.internal.BundleGenerator; |
26 import org.tmatesoft.hg.internal.Internals; | |
27 import org.tmatesoft.hg.internal.PhasesHelper; | |
25 import org.tmatesoft.hg.internal.RepositoryComparator; | 28 import org.tmatesoft.hg.internal.RepositoryComparator; |
29 import org.tmatesoft.hg.internal.RevisionSet; | |
26 import org.tmatesoft.hg.repo.HgBookmarks; | 30 import org.tmatesoft.hg.repo.HgBookmarks; |
27 import org.tmatesoft.hg.repo.HgBundle; | 31 import org.tmatesoft.hg.repo.HgBundle; |
28 import org.tmatesoft.hg.repo.HgChangelog; | 32 import org.tmatesoft.hg.repo.HgChangelog; |
29 import org.tmatesoft.hg.repo.HgInternals; | 33 import org.tmatesoft.hg.repo.HgInternals; |
30 import org.tmatesoft.hg.repo.HgInvalidStateException; | 34 import org.tmatesoft.hg.repo.HgInvalidStateException; |
31 import org.tmatesoft.hg.repo.HgLookup; | 35 import org.tmatesoft.hg.repo.HgLookup; |
32 import org.tmatesoft.hg.repo.HgParentChildMap; | 36 import org.tmatesoft.hg.repo.HgParentChildMap; |
37 import org.tmatesoft.hg.repo.HgPhase; | |
33 import org.tmatesoft.hg.repo.HgRemoteRepository; | 38 import org.tmatesoft.hg.repo.HgRemoteRepository; |
34 import org.tmatesoft.hg.repo.HgRepository; | 39 import org.tmatesoft.hg.repo.HgRepository; |
35 import org.tmatesoft.hg.repo.HgRuntimeException; | 40 import org.tmatesoft.hg.repo.HgRuntimeException; |
36 import org.tmatesoft.hg.util.CancelledException; | 41 import org.tmatesoft.hg.util.CancelledException; |
37 import org.tmatesoft.hg.util.Pair; | 42 import org.tmatesoft.hg.util.Pair; |
38 import org.tmatesoft.hg.util.ProgressSupport; | 43 import org.tmatesoft.hg.util.ProgressSupport; |
44 import org.tmatesoft.hg.util.LogFacility.Severity; | |
39 | 45 |
40 /** | 46 /** |
41 * | 47 * |
42 * @author Artem Tikhomirov | 48 * @author Artem Tikhomirov |
43 * @author TMate Software Ltd. | 49 * @author TMate Software Ltd. |
61 try { | 67 try { |
62 progress.start(100); | 68 progress.start(100); |
63 // | 69 // |
64 // find out missing | 70 // find out missing |
65 // TODO refactor same code in HgOutgoingCommand #getComparator and #getParentHelper | 71 // TODO refactor same code in HgOutgoingCommand #getComparator and #getParentHelper |
66 final HgParentChildMap<HgChangelog> parentHelper = new HgParentChildMap<HgChangelog>(repo.getChangelog()); | 72 final HgChangelog clog = repo.getChangelog(); |
73 final HgParentChildMap<HgChangelog> parentHelper = new HgParentChildMap<HgChangelog>(clog); | |
67 parentHelper.init(); | 74 parentHelper.init(); |
68 final RepositoryComparator comparator = new RepositoryComparator(parentHelper, remoteRepo); | 75 final RepositoryComparator comparator = new RepositoryComparator(parentHelper, remoteRepo); |
69 comparator.compare(new ProgressSupport.Sub(progress, 50), getCancelSupport(null, true)); | 76 comparator.compare(new ProgressSupport.Sub(progress, 50), getCancelSupport(null, true)); |
70 List<Nodeid> l = comparator.getLocalOnlyRevisions(); | 77 List<Nodeid> l = comparator.getLocalOnlyRevisions(); |
71 // | 78 // |
72 // prepare bundle | 79 // prepare bundle |
73 BundleGenerator bg = new BundleGenerator(HgInternals.getImplementationRepo(repo)); | 80 final Internals implRepo = HgInternals.getImplementationRepo(repo); |
81 BundleGenerator bg = new BundleGenerator(implRepo); | |
74 File bundleFile = bg.create(l); | 82 File bundleFile = bg.create(l); |
75 progress.worked(20); | 83 progress.worked(20); |
76 HgBundle b = new HgLookup(repo.getSessionContext()).loadBundle(bundleFile); | 84 HgBundle b = new HgLookup(repo.getSessionContext()).loadBundle(bundleFile); |
77 // | 85 // |
78 // send changes | 86 // send changes |
79 remoteRepo.unbundle(b, comparator.getRemoteHeads()); | 87 remoteRepo.unbundle(b, comparator.getRemoteHeads()); |
80 progress.worked(20); | 88 progress.worked(20); |
81 // | 89 // |
82 // FIXME update phase information | 90 // update phase information |
83 // remote.listkeys("phases"); | 91 PhasesHelper phaseHelper = new PhasesHelper(implRepo, parentHelper); |
92 if (phaseHelper.isCapableOfPhases()) { | |
93 RevisionSet outgoing = new RevisionSet(l); | |
94 RevisionSet presentSecret = phaseHelper.allSecret(); | |
95 RevisionSet presentDraft = phaseHelper.allDraft(); | |
96 RevisionSet secretLeft, draftLeft; | |
97 HgRemoteRepository.Phases remotePhases = remoteRepo.getPhases(); | |
98 if (remotePhases.isPublishingServer()) { | |
99 // although it's unlikely outgoing would affect secret changesets, | |
100 // it doesn't hurt to check secret roots along with draft ones | |
101 secretLeft = presentSecret.subtract(outgoing); | |
102 draftLeft = presentDraft.subtract(outgoing); | |
103 } else { | |
104 // shall merge local and remote phase states | |
105 ArrayList<Nodeid> knownRemoteDraftRoots = new ArrayList<Nodeid>(); | |
106 for (Nodeid rdr : remotePhases.draftRoots()) { | |
107 if (clog.isKnown(rdr)) { | |
108 knownRemoteDraftRoots.add(rdr); | |
109 } | |
110 } | |
111 // childrenOf(knownRemoteDraftRoots) is everything remote may treat as Draft | |
112 RevisionSet remoteDrafts = new RevisionSet(parentHelper.childrenOf(knownRemoteDraftRoots)); | |
113 List<Nodeid> localChildrenNotSent = parentHelper.childrenOf(outgoing.heads(parentHelper).asList()); | |
114 // remote shall know only what we've sent, subtract revisions we didn't actually sent | |
115 remoteDrafts = remoteDrafts.subtract(new RevisionSet(localChildrenNotSent)); | |
116 // if there's a remote draft root that points to revision we know is public | |
117 RevisionSet remoteDraftsLocallyPublic = remoteDrafts.subtract(presentSecret).subtract(presentDraft); | |
118 if (!remoteDraftsLocallyPublic.isEmpty()) { | |
119 // foreach remoteDraftsLocallyPublic.heads() do push Draft->Public | |
120 for (Nodeid n : remoteDraftsLocallyPublic.heads(parentHelper)) { | |
121 try { | |
122 remoteRepo.updatePhase(HgPhase.Draft, HgPhase.Public, n); | |
123 } catch (HgRemoteConnectionException ex) { | |
124 implRepo.getLog().dump(getClass(), Severity.Error, ex, String.format("Failed to update phase of %s", n.shortNotation())); | |
125 } | |
126 } | |
127 remoteDrafts = remoteDrafts.subtract(remoteDraftsLocallyPublic); | |
128 } | |
129 // revisions that cease to be secret (gonna become Public), e.g. someone else pushed them | |
130 RevisionSet secretGone = presentSecret.intersect(remoteDrafts); | |
131 // trace parents of these published secret revisions | |
132 RevisionSet secretMadePublic = presentSecret.parentsOf(secretGone, parentHelper); | |
133 secretLeft = presentSecret.subtract(secretGone).subtract(secretMadePublic); | |
134 // same for drafts | |
135 RevisionSet draftGone = presentDraft.intersect(remoteDrafts); | |
136 RevisionSet draftMadePublic = presentDraft.parentsOf(draftGone, parentHelper); | |
137 draftLeft = presentDraft.subtract(draftGone).subtract(draftMadePublic); | |
138 } | |
139 final RevisionSet newDraftRoots = draftLeft.roots(parentHelper); | |
140 final RevisionSet newSecretRoots = secretLeft.roots(parentHelper); | |
141 phaseHelper.updateRoots(newDraftRoots.asList(), newSecretRoots.asList()); | |
142 } | |
84 progress.worked(5); | 143 progress.worked(5); |
85 // | 144 // |
86 // update bookmark information | 145 // update bookmark information |
87 HgBookmarks localBookmarks = repo.getBookmarks(); | 146 HgBookmarks localBookmarks = repo.getBookmarks(); |
88 if (!localBookmarks.getAllBookmarks().isEmpty()) { | 147 if (!localBookmarks.getAllBookmarks().isEmpty()) { |
89 for (Pair<String,Nodeid> bm : remoteRepo.bookmarks()) { | 148 for (Pair<String,Nodeid> bm : remoteRepo.getBookmarks()) { |
90 Nodeid localRevision = localBookmarks.getRevision(bm.first()); | 149 Nodeid localRevision = localBookmarks.getRevision(bm.first()); |
91 if (localRevision == null || !parentHelper.knownNode(bm.second())) { | 150 if (localRevision == null || !parentHelper.knownNode(bm.second())) { |
92 continue; | 151 continue; |
93 } | 152 } |
94 // we know both localRevision and revision of remote bookmark, | 153 // we know both localRevision and revision of remote bookmark, |
96 if (parentHelper.isChild(bm.second(), localRevision)) { | 155 if (parentHelper.isChild(bm.second(), localRevision)) { |
97 remoteRepo.updateBookmark(bm.first(), bm.second(), localRevision); | 156 remoteRepo.updateBookmark(bm.first(), bm.second(), localRevision); |
98 } | 157 } |
99 } | 158 } |
100 } | 159 } |
101 // remote.listkeys("bookmarks"); | |
102 // XXX WTF is obsolete in namespaces key?? | 160 // XXX WTF is obsolete in namespaces key?? |
103 progress.worked(5); | 161 progress.worked(5); |
104 } catch (IOException ex) { | 162 } catch (IOException ex) { |
105 throw new HgIOException(ex.getMessage(), null); // XXX not a nice idea to throw IOException from BundleGenerator#create | 163 throw new HgIOException(ex.getMessage(), null); // XXX not a nice idea to throw IOException from BundleGenerator#create |
106 } catch (HgRepositoryNotFoundException ex) { | 164 } catch (HgRepositoryNotFoundException ex) { |
118 * To test, start a server: | 176 * To test, start a server: |
119 * $ hg --config web.allow_push=* --config web.push_ssl=False --config server.validate=True --debug serve | 177 * $ hg --config web.allow_push=* --config web.push_ssl=False --config server.validate=True --debug serve |
120 */ | 178 */ |
121 public static void main(String[] args) throws Exception { | 179 public static void main(String[] args) throws Exception { |
122 final HgLookup hgLookup = new HgLookup(); | 180 final HgLookup hgLookup = new HgLookup(); |
123 HgRepository r = hgLookup.detect("/home/artem/hg/junit-test-repos/log-1/"); | 181 HgRepository r = hgLookup.detect("/home/artem/hg/test-phases/"); |
124 HgRemoteRepository rr = hgLookup.detect(new URL("http://localhost:8000/")); | 182 HgRemoteRepository rr = hgLookup.detect(new URL("http://localhost:8000/")); |
125 new HgPushCommand(r).destination(rr).execute(); | 183 new HgPushCommand(r).destination(rr).execute(); |
126 } | 184 } |
127 } | 185 } |