Mercurial > hg4j
comparison test/org/tmatesoft/hg/test/TestPush.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 | 6e98d34eaca8 |
children | 629a7370554c |
comparison
equal
deleted
inserted
replaced
651:6e98d34eaca8 | 652:cd77bf51b562 |
---|---|
24 import java.net.MalformedURLException; | 24 import java.net.MalformedURLException; |
25 import java.net.URL; | 25 import java.net.URL; |
26 import java.util.ArrayList; | 26 import java.util.ArrayList; |
27 import java.util.List; | 27 import java.util.List; |
28 | 28 |
29 import org.junit.Assert; | |
30 import org.junit.Rule; | 29 import org.junit.Rule; |
31 import org.junit.Test; | 30 import org.junit.Test; |
32 import org.tmatesoft.hg.core.HgCheckoutCommand; | 31 import org.tmatesoft.hg.core.HgCheckoutCommand; |
33 import org.tmatesoft.hg.core.HgCommitCommand; | 32 import org.tmatesoft.hg.core.HgCommitCommand; |
34 import org.tmatesoft.hg.core.HgOutgoingCommand; | 33 import org.tmatesoft.hg.core.HgOutgoingCommand; |
35 import org.tmatesoft.hg.core.HgPushCommand; | 34 import org.tmatesoft.hg.core.HgPushCommand; |
36 import org.tmatesoft.hg.core.Nodeid; | 35 import org.tmatesoft.hg.core.Nodeid; |
37 import org.tmatesoft.hg.internal.PhasesHelper; | 36 import org.tmatesoft.hg.internal.PhasesHelper; |
38 import org.tmatesoft.hg.internal.RevisionSet; | 37 import org.tmatesoft.hg.internal.RevisionSet; |
38 import org.tmatesoft.hg.repo.HgBookmarks; | |
39 import org.tmatesoft.hg.repo.HgChangelog; | 39 import org.tmatesoft.hg.repo.HgChangelog; |
40 import org.tmatesoft.hg.repo.HgInternals; | 40 import org.tmatesoft.hg.repo.HgInternals; |
41 import org.tmatesoft.hg.repo.HgLookup; | 41 import org.tmatesoft.hg.repo.HgLookup; |
42 import org.tmatesoft.hg.repo.HgPhase; | |
42 import org.tmatesoft.hg.repo.HgRemoteRepository; | 43 import org.tmatesoft.hg.repo.HgRemoteRepository; |
43 import org.tmatesoft.hg.repo.HgRepository; | 44 import org.tmatesoft.hg.repo.HgRepository; |
44 | 45 |
45 /** | 46 /** |
46 * @author Artem Tikhomirov | 47 * @author Artem Tikhomirov |
99 } | 100 } |
100 } | 101 } |
101 | 102 |
102 @Test | 103 @Test |
103 public void testPushToNonPublishingServer() throws Exception { | 104 public void testPushToNonPublishingServer() throws Exception { |
104 Assert.fail(); | 105 // check drafts are same as on server |
106 // copy, not clone as latter updates phase information | |
107 File srcRepoLoc = RepoUtils.copyRepoToTempLocation("test-phases", "test-push-nopub-src"); | |
108 File dstRepoLoc = RepoUtils.initEmptyTempRepo("test-push-nopub-dst"); | |
109 File f1 = new File(srcRepoLoc, "hello.c"); | |
110 assertTrue("[sanity]", f1.canWrite()); | |
111 HgServer server = new HgServer().publishing(false).start(dstRepoLoc); | |
112 try { | |
113 final HgLookup hgLookup = new HgLookup(); | |
114 final HgRepository srcRepo = hgLookup.detect(srcRepoLoc); | |
115 final HgRemoteRepository dstRemote = hgLookup.detect(server.getURL()); | |
116 PhasesHelper phaseHelper = new PhasesHelper(HgInternals.getImplementationRepo(srcRepo)); | |
117 final RevisionSet allDraft = phaseHelper.allDraft(); | |
118 assertFalse("[sanity]", allDraft.isEmpty()); | |
119 final int publicCsetToBranchAt = 4; | |
120 assertEquals("[sanity]", HgPhase.Public, phaseHelper.getPhase(publicCsetToBranchAt, null)); | |
121 // in addition to existing draft csets, add one more draft, branching at some other public revision | |
122 new HgCheckoutCommand(srcRepo).changeset(publicCsetToBranchAt).clean(true).execute(); | |
123 RepoUtils.modifyFileAppend(f1, "// aaa"); | |
124 final HgCommitCommand commitCmd = new HgCommitCommand(srcRepo).message("Commit aaa"); | |
125 assertTrue(commitCmd.execute().isOk()); | |
126 Nodeid newCommit = commitCmd.getCommittedRevision(); | |
127 // | |
128 new HgPushCommand(srcRepo).destination(dstRemote).execute(); | |
129 HgRepository dstRepo = hgLookup.detect(dstRepoLoc); | |
130 final HgChangelog srcClog = srcRepo.getChangelog(); | |
131 final HgChangelog dstClog = dstRepo.getChangelog(); | |
132 // refresh PhasesHelper | |
133 phaseHelper = new PhasesHelper(HgInternals.getImplementationRepo(srcRepo)); | |
134 // check if phase didn't change | |
135 errorCollector.assertEquals(HgPhase.Draft, phaseHelper.getPhase(srcClog.getRevisionIndex(newCommit), newCommit)); | |
136 for (Nodeid n : allDraft) { | |
137 // check drafts from src were actually pushed to dst | |
138 errorCollector.assertTrue(dstClog.isKnown(n)); | |
139 // check drafts didn't change their phase | |
140 errorCollector.assertEquals(HgPhase.Draft, phaseHelper.getPhase(srcClog.getRevisionIndex(n), n)); | |
141 } | |
142 } finally { | |
143 server.stop(); | |
144 } | |
105 } | 145 } |
106 | 146 |
147 /** | |
148 * If server lists revisions we know as drafts as public, update them locally | |
149 */ | |
150 @Test | |
151 public void testPushUpdatesPublishedDrafts() throws Exception { | |
152 /* o r9, secret | |
153 * | o r8, draft | |
154 * | | | |
155 * | o r7, draft | |
156 * o | r6, secret | |
157 * | / | |
158 * o r5, draft | |
159 * | | |
160 * o r4, public | |
161 */ | |
162 // remote: r5 -> public, r6 -> draft, r8 -> secret | |
163 // local: new draft from r4, push | |
164 File srcRepoLoc = RepoUtils.copyRepoToTempLocation("test-phases", "test-push-phase-update-1-src"); | |
165 File dstRepoLoc = RepoUtils.copyRepoToTempLocation("test-phases", "test-push-phase-update-1-dst"); | |
166 File f1 = new File(srcRepoLoc, "hello.c"); | |
167 assertTrue("[sanity]", f1.canWrite()); | |
168 final HgLookup hgLookup = new HgLookup(); | |
169 final HgRepository srcRepo = hgLookup.detect(srcRepoLoc); | |
170 final ExecHelper dstRun = new ExecHelper(new OutputParser.Stub(), dstRepoLoc); | |
171 final int publicCsetToBranchAt = 4; | |
172 final int r5 = 5, r6 = 6, r8 = 8; | |
173 PhasesHelper srcPhase = new PhasesHelper(HgInternals.getImplementationRepo(srcRepo)); | |
174 assertEquals("[sanity]", HgPhase.Draft, srcPhase.getPhase(r5, null)); | |
175 assertEquals("[sanity]", HgPhase.Secret, srcPhase.getPhase(r6, null)); | |
176 assertEquals("[sanity]", HgPhase.Draft, srcPhase.getPhase(r8, null)); | |
177 // change phases in repository of remote server: | |
178 dstRun.exec("hg", "phase", "--public", String.valueOf(r5)); | |
179 assertEquals(0, dstRun.getExitValue()); | |
180 dstRun.exec("hg", "phase", "--draft", String.valueOf(r6)); | |
181 assertEquals(0, dstRun.getExitValue()); | |
182 dstRun.exec("hg", "phase", "--secret", "--force", String.valueOf(r8)); | |
183 assertEquals(0, dstRun.getExitValue()); | |
184 HgServer server = new HgServer().publishing(false).start(dstRepoLoc); | |
185 try { | |
186 final HgRemoteRepository dstRemote = hgLookup.detect(server.getURL()); | |
187 // commit new draft head | |
188 new HgCheckoutCommand(srcRepo).changeset(publicCsetToBranchAt).clean(true).execute(); | |
189 RepoUtils.modifyFileAppend(f1, "// aaa"); | |
190 final HgCommitCommand commitCmd = new HgCommitCommand(srcRepo).message("Commit aaa"); | |
191 assertTrue(commitCmd.execute().isOk()); | |
192 final Nodeid newCommit = commitCmd.getCommittedRevision(); | |
193 // | |
194 new HgPushCommand(srcRepo).destination(dstRemote).execute(); | |
195 // refresh phase information | |
196 srcPhase = new PhasesHelper(HgInternals.getImplementationRepo(srcRepo)); | |
197 // r5 and r6 are changed to match server phases (more exposed) | |
198 errorCollector.assertEquals(HgPhase.Public, srcPhase.getPhase(r5, null)); | |
199 errorCollector.assertEquals(HgPhase.Draft, srcPhase.getPhase(r6, null)); | |
200 // r8 is secret on server, locally can't make it less exposed though | |
201 errorCollector.assertEquals(HgPhase.Draft, srcPhase.getPhase(r8, null)); | |
202 // | |
203 HgRepository dstRepo = hgLookup.detect(dstRepoLoc); | |
204 final HgChangelog dstClog = dstRepo.getChangelog(); | |
205 assertTrue(dstClog.isKnown(newCommit)); | |
206 PhasesHelper dstPhase = new PhasesHelper(HgInternals.getImplementationRepo(dstRepo)); | |
207 errorCollector.assertEquals(HgPhase.Draft, dstPhase.getPhase(dstClog.getRevisionIndex(newCommit), newCommit)); | |
208 // the one that was secret is draft now | |
209 errorCollector.assertEquals(HgPhase.Draft, srcPhase.getPhase(r8, null)); | |
210 } finally { | |
211 server.stop(); | |
212 } | |
213 } | |
214 | |
215 /** | |
216 * update phases of local revisions and push changes | |
217 */ | |
218 @Test | |
219 public void testPushPublishAndUpdates() throws Exception { | |
220 File srcRepoLoc = RepoUtils.copyRepoToTempLocation("test-phases", "test-push-phase-update-2-src"); | |
221 File dstRepoLoc = RepoUtils.initEmptyTempRepo("test-push-phase-update-1-dst"); | |
222 final int r4 = 4, r5 = 5, r6 = 6, r9 = 9; | |
223 HgServer server = new HgServer().publishing(false).start(dstRepoLoc); | |
224 try { | |
225 final HgLookup hgLookup = new HgLookup(); | |
226 final HgRepository srcRepo = hgLookup.detect(srcRepoLoc); | |
227 final HgRemoteRepository dstRemote = hgLookup.detect(server.getURL()); | |
228 new HgPushCommand(srcRepo).destination(dstRemote).execute(); | |
229 // | |
230 // make sure pushed repository got same draft root | |
231 final Nodeid r4PublicHead = srcRepo.getChangelog().getRevision(r4); | |
232 final Nodeid r5DraftRoot = srcRepo.getChangelog().getRevision(r5); | |
233 HgRepository dstRepo = hgLookup.detect(dstRepoLoc); | |
234 final HgChangelog dstClog = dstRepo.getChangelog(); | |
235 PhasesHelper dstPhase = new PhasesHelper(HgInternals.getImplementationRepo(dstRepo)); | |
236 assertEquals(HgPhase.Public, dstPhase.getPhase(dstClog.getRevisionIndex(r4PublicHead), r4PublicHead)); | |
237 assertEquals(HgPhase.Draft, dstPhase.getPhase(dstClog.getRevisionIndex(r5DraftRoot), r5DraftRoot)); | |
238 // | |
239 // now, graduate some local revisions, r5:draft->public, r6:secret->public, r9: secret->draft | |
240 final ExecHelper srcRun = new ExecHelper(new OutputParser.Stub(), srcRepoLoc); | |
241 srcRun.exec("hg", "phase", "--public", String.valueOf(r5)); | |
242 srcRun.exec("hg", "phase", "--public", String.valueOf(r6)); | |
243 srcRun.exec("hg", "phase", "--draft", String.valueOf(r9)); | |
244 // PhaseHelper shall be new for the command, and would pick up these external changes | |
245 new HgPushCommand(srcRepo).destination(dstRemote).execute(); | |
246 final Nodeid r6Nodeid = srcRepo.getChangelog().getRevision(r6); | |
247 final Nodeid r9Nodeid = srcRepo.getChangelog().getRevision(r9); | |
248 // refresh | |
249 dstPhase = new PhasesHelper(HgInternals.getImplementationRepo(dstRepo)); | |
250 // not errorCollector as subsequent code would fail if these secret revs didn't get into dst | |
251 assertTrue(dstClog.isKnown(r6Nodeid)); | |
252 assertTrue(dstClog.isKnown(r9Nodeid)); | |
253 errorCollector.assertEquals(HgPhase.Public, dstPhase.getPhase(dstClog.getRevisionIndex(r5DraftRoot), r5DraftRoot)); | |
254 errorCollector.assertEquals(HgPhase.Public, dstPhase.getPhase(dstClog.getRevisionIndex(r6Nodeid), r6Nodeid)); | |
255 errorCollector.assertEquals(HgPhase.Draft, dstPhase.getPhase(dstClog.getRevisionIndex(r9Nodeid), r9Nodeid)); | |
256 } finally { | |
257 server.stop(); | |
258 } | |
259 } | |
260 | |
261 | |
107 @Test | 262 @Test |
108 public void testPushToPublishingServer() throws Exception { | 263 public void testPushToPublishingServer() throws Exception { |
109 Assert.fail(); | 264 // copy, not clone as latter updates phase information |
265 File srcRepoLoc = RepoUtils.copyRepoToTempLocation("test-phases", "test-push-pub-src"); | |
266 File dstRepoLoc = RepoUtils.initEmptyTempRepo("test-push-pub-dst"); | |
267 HgServer server = new HgServer().publishing(true).start(dstRepoLoc); | |
268 try { | |
269 final HgLookup hgLookup = new HgLookup(); | |
270 final HgRepository srcRepo = hgLookup.detect(srcRepoLoc); | |
271 final HgRemoteRepository dstRemote = hgLookup.detect(server.getURL()); | |
272 PhasesHelper phaseHelper = new PhasesHelper(HgInternals.getImplementationRepo(srcRepo)); | |
273 final RevisionSet allDraft = phaseHelper.allDraft(); | |
274 assertFalse("[sanity]", allDraft.isEmpty()); | |
275 // push all changes | |
276 new HgPushCommand(srcRepo).destination(dstRemote).execute(); | |
277 HgRepository dstRepo = hgLookup.detect(dstRepoLoc); | |
278 final HgChangelog srcClog = srcRepo.getChangelog(); | |
279 final HgChangelog dstClog = dstRepo.getChangelog(); | |
280 // refresh PhasesHelper | |
281 phaseHelper = new PhasesHelper(HgInternals.getImplementationRepo(srcRepo)); | |
282 for (Nodeid n : allDraft) { | |
283 // check drafts from src were actually pushed to dst | |
284 errorCollector.assertTrue(dstClog.isKnown(n)); | |
285 // check drafts became public | |
286 errorCollector.assertEquals(HgPhase.Public, phaseHelper.getPhase(srcClog.getRevisionIndex(n), n)); | |
287 } | |
288 } finally { | |
289 server.stop(); | |
290 } | |
110 } | 291 } |
111 | 292 |
112 @Test | 293 @Test |
113 public void testPushSecretChangesets() throws Exception { | 294 public void testPushSecretChangesets() throws Exception { |
114 // copy, not clone as latter updates phase information | 295 // copy, not clone as latter updates phase information |
135 } | 316 } |
136 } | 317 } |
137 | 318 |
138 @Test | 319 @Test |
139 public void testUpdateBookmarkOnPush() throws Exception { | 320 public void testUpdateBookmarkOnPush() throws Exception { |
140 Assert.fail(); | 321 File srcRepoLoc = RepoUtils.cloneRepoToTempLocation("test-annotate", "test-push-src", false); |
322 File dstRepoLoc = RepoUtils.cloneRepoToTempLocation("test-annotate", "test-push-dst", false); | |
323 final ExecHelper srcRun = new ExecHelper(new OutputParser.Stub(), srcRepoLoc); | |
324 final ExecHelper dstRun = new ExecHelper(new OutputParser.Stub(), dstRepoLoc); | |
325 File f1 = new File(srcRepoLoc, "file1"); | |
326 assertTrue("[sanity]", f1.canWrite()); | |
327 // | |
328 final String bm1 = "mark1", bm2 = "mark2", bm3 = "mark3", bm4 = "mark4", bm5 = "mark5"; | |
329 final int bm2Local = 1, bm2Remote = 6, bm3Local = 7, bm3Remote = 2, bm_4_5 = 3; | |
330 // 1) bm1 - local active bookmark, check that push updates in remote | |
331 srcRun.exec("hg", "bookmark", bm1); | |
332 dstRun.exec("hg", "bookmark", "-r", "8", bm1); | |
333 // 2) bm2 - local points to ancestor of revision remote points to | |
334 srcRun.exec("hg", "bookmark", "-r", String.valueOf(bm2Local), bm2); | |
335 dstRun.exec("hg", "bookmark", "-r", String.valueOf(bm2Remote), bm2); | |
336 // 3) bm3 - remote points to ancestor of revision local one points to | |
337 srcRun.exec("hg", "bookmark", "-r", String.valueOf(bm3Local), bm3); | |
338 dstRun.exec("hg", "bookmark", "-r", String.valueOf(bm3Remote), bm3); | |
339 // 4) bm4 - remote bookmark, not known locally | |
340 dstRun.exec("hg", "bookmark", "-r", String.valueOf(bm_4_5), bm4); | |
341 // 5) bm5 - local bookmark, not known remotely | |
342 srcRun.exec("hg", "bookmark", "-r", String.valueOf(bm_4_5), bm5); | |
343 // | |
344 HgServer server = new HgServer().start(dstRepoLoc); | |
345 try { | |
346 final HgLookup hgLookup = new HgLookup(); | |
347 final HgRepository srcRepo = hgLookup.detect(srcRepoLoc); | |
348 final HgRemoteRepository dstRemote = hgLookup.detect(server.getURL()); | |
349 RepoUtils.modifyFileAppend(f1, "change1"); | |
350 final HgCommitCommand commitCmd = new HgCommitCommand(srcRepo).message("Commit 1"); | |
351 assertTrue(commitCmd.execute().isOk()); | |
352 assertEquals(bm1, srcRepo.getBookmarks().getActiveBookmarkName()); | |
353 assertEquals(commitCmd.getCommittedRevision(), srcRepo.getBookmarks().getRevision(bm1)); | |
354 // | |
355 new HgPushCommand(srcRepo).destination(dstRemote).execute(); | |
356 Thread.sleep(300); // let the server perform the update | |
357 // | |
358 HgBookmarks srcBookmarks = srcRepo.getBookmarks(); | |
359 final HgChangelog srcClog = srcRepo.getChangelog(); | |
360 // first, check local bookmarks are intact | |
361 errorCollector.assertEquals(srcClog.getRevision(bm2Local), srcBookmarks.getRevision(bm2)); | |
362 errorCollector.assertEquals(srcClog.getRevision(bm3Local), srcBookmarks.getRevision(bm3)); | |
363 errorCollector.assertEquals(null, srcBookmarks.getRevision(bm4)); | |
364 errorCollector.assertEquals(srcClog.getRevision(bm_4_5), srcBookmarks.getRevision(bm5)); | |
365 // now, check remote bookmarks were touched | |
366 HgRepository dstRepo = hgLookup.detect(dstRepoLoc); | |
367 HgBookmarks dstBookmarks = dstRepo.getBookmarks(); | |
368 final HgChangelog dstClog = dstRepo.getChangelog(); | |
369 // bm1 changed and points to newly pushed commit. | |
370 // if the test fails (bm1 points to r8), chances are server didn't manage to update | |
371 // bookmarks yet (there's Thread.sleep() above to give it a chance). | |
372 errorCollector.assertEquals(commitCmd.getCommittedRevision(), dstBookmarks.getRevision(bm1)); | |
373 // bm2 didn't change | |
374 errorCollector.assertEquals(dstClog.getRevision(bm2Remote), dstBookmarks.getRevision(bm2)); | |
375 // bm3 did change, now points to value we've got in srcRepo | |
376 errorCollector.assertEquals(srcClog.getRevision(bm3Local), dstBookmarks.getRevision(bm3)); | |
377 // bm4 is not affected | |
378 errorCollector.assertEquals(dstClog.getRevision(bm_4_5), dstBookmarks.getRevision(bm4)); | |
379 // bm5 is not known remotely | |
380 errorCollector.assertEquals(null, dstBookmarks.getRevision(bm5)); | |
381 } finally { | |
382 server.stop(); | |
383 } | |
141 } | 384 } |
142 | 385 |
143 | 386 |
144 private void checkRepositoriesAreSame(HgRepository srcRepo, HgRepository dstRepo) { | 387 private void checkRepositoriesAreSame(HgRepository srcRepo, HgRepository dstRepo) { |
145 errorCollector.assertEquals(srcRepo.getChangelog().getRevisionCount(), dstRepo.getChangelog().getRevisionCount()); | 388 errorCollector.assertEquals(srcRepo.getChangelog().getRevisionCount(), dstRepo.getChangelog().getRevisionCount()); |
147 errorCollector.assertEquals(srcRepo.getChangelog().getRevision(TIP), dstRepo.getChangelog().getRevision(TIP)); | 390 errorCollector.assertEquals(srcRepo.getChangelog().getRevision(TIP), dstRepo.getChangelog().getRevision(TIP)); |
148 } | 391 } |
149 | 392 |
150 static class HgServer { | 393 static class HgServer { |
151 private Process serverProcess; | 394 private Process serverProcess; |
395 private boolean publish = true; | |
396 | |
397 public HgServer publishing(boolean pub) { | |
398 publish = pub; | |
399 return this; | |
400 } | |
152 | 401 |
153 public HgServer start(File dir) throws IOException, InterruptedException { | 402 public HgServer start(File dir) throws IOException, InterruptedException { |
154 if (serverProcess != null) { | 403 if (serverProcess != null) { |
155 stop(); | 404 stop(); |
156 } | 405 } |
162 cmdline.add("web.push_ssl=False"); | 411 cmdline.add("web.push_ssl=False"); |
163 cmdline.add("--config"); | 412 cmdline.add("--config"); |
164 cmdline.add("server.validate=True"); | 413 cmdline.add("server.validate=True"); |
165 cmdline.add("--config"); | 414 cmdline.add("--config"); |
166 cmdline.add(String.format("web.port=%d", port())); | 415 cmdline.add(String.format("web.port=%d", port())); |
416 if (!publish) { | |
417 cmdline.add("--config"); | |
418 cmdline.add("phases.publish=False"); | |
419 } | |
167 cmdline.add("serve"); | 420 cmdline.add("serve"); |
168 serverProcess = new ProcessBuilder(cmdline).directory(dir).start(); | 421 serverProcess = new ProcessBuilder(cmdline).directory(dir).start(); |
169 Thread.sleep(500); | 422 Thread.sleep(500); |
170 return this; | 423 return this; |
171 } | 424 } |