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 }