# HG changeset patch # User Artem Tikhomirov # Date 1372855110 -7200 # Node ID 629a7370554c434e91d81d297580a06dfd4d1fc4 # Parent cd77bf51b5628f1268088ff669bab42aeb917425 Tests for recent changes in HgParentChildMap and RepositoryComparator (outgoing to respect drafts and Issue 47) diff -r cd77bf51b562 -r 629a7370554c build.xml --- a/build.xml Tue Jul 02 23:21:16 2013 +0200 +++ b/build.xml Wed Jul 03 14:38:30 2013 +0200 @@ -111,6 +111,7 @@ + diff -r cd77bf51b562 -r 629a7370554c src/org/tmatesoft/hg/core/HgOutgoingCommand.java --- a/src/org/tmatesoft/hg/core/HgOutgoingCommand.java Tue Jul 02 23:21:16 2013 +0200 +++ b/src/org/tmatesoft/hg/core/HgOutgoingCommand.java Wed Jul 03 14:38:30 2013 +0200 @@ -21,7 +21,9 @@ import java.util.TreeSet; import org.tmatesoft.hg.internal.Internals; +import org.tmatesoft.hg.internal.PhasesHelper; import org.tmatesoft.hg.internal.RepositoryComparator; +import org.tmatesoft.hg.internal.RevisionSet; import org.tmatesoft.hg.repo.HgChangelog; import org.tmatesoft.hg.repo.HgParentChildMap; import org.tmatesoft.hg.repo.HgRemoteRepository; @@ -103,8 +105,7 @@ public List executeLite() throws HgRemoteConnectionException, HgException, CancelledException { final ProgressSupport ps = getProgressSupport(null); try { - ps.start(10); - return getComparator(new ProgressSupport.Sub(ps, 5), getCancelSupport(null, true)).getLocalOnlyRevisions(); + return getOutgoingRevisions(ps, getCancelSupport(null, true)); } catch (HgRuntimeException ex) { throw new HgLibraryFailureException(ex); } finally { @@ -128,10 +129,16 @@ final ProgressSupport ps = getProgressSupport(handler); final CancelSupport cs = getCancelSupport(handler, true); try { - ps.start(-1); - ChangesetTransformer inspector = new ChangesetTransformer(localRepo, handler, getParentHelper(), ps, cs); + ps.start(200); + ChangesetTransformer inspector = new ChangesetTransformer(localRepo, handler, getParentHelper(), new ProgressSupport.Sub(ps, 100), cs); inspector.limitBranches(branches); - getComparator(new ProgressSupport.Sub(ps, 1), cs).visitLocalOnlyRevisions(inspector); + List out = getOutgoingRevisions(new ProgressSupport.Sub(ps, 100), cs); + int[] outRevIndex = new int[out.size()]; + int i = 0; + for (Nodeid o : out) { + outRevIndex[i++] = localRepo.getChangelog().getRevisionIndex(o); + } + localRepo.getChangelog().range(inspector, outRevIndex); inspector.checkFailure(); } catch (HgRuntimeException ex) { throw new HgLibraryFailureException(ex); @@ -159,4 +166,17 @@ return parentHelper; } + + private List getOutgoingRevisions(ProgressSupport ps, CancelSupport cs) throws HgRemoteConnectionException, HgException, CancelledException { + ps.start(10); + final RepositoryComparator c = getComparator(new ProgressSupport.Sub(ps, 5), cs); + List local = c.getLocalOnlyRevisions(); + ps.worked(3); + PhasesHelper phaseHelper = new PhasesHelper(Internals.getInstance(localRepo)); + if (phaseHelper.isCapableOfPhases() && phaseHelper.withSecretRoots()) { + local = new RevisionSet(local).subtract(phaseHelper.allSecret()).asList(); + } + ps.worked(2); + return local; + } } diff -r cd77bf51b562 -r 629a7370554c src/org/tmatesoft/hg/core/HgPushCommand.java --- a/src/org/tmatesoft/hg/core/HgPushCommand.java Tue Jul 02 23:21:16 2013 +0200 +++ b/src/org/tmatesoft/hg/core/HgPushCommand.java Wed Jul 03 14:38:30 2013 +0200 @@ -18,7 +18,6 @@ import java.io.File; import java.io.IOException; -import java.net.URL; import java.util.ArrayList; import java.util.List; @@ -39,10 +38,10 @@ import org.tmatesoft.hg.repo.HgRepository; import org.tmatesoft.hg.repo.HgRuntimeException; import org.tmatesoft.hg.util.CancelledException; +import org.tmatesoft.hg.util.LogFacility.Severity; import org.tmatesoft.hg.util.Outcome; import org.tmatesoft.hg.util.Pair; import org.tmatesoft.hg.util.ProgressSupport; -import org.tmatesoft.hg.util.LogFacility.Severity; /** * @@ -220,15 +219,4 @@ remoteDrafts = remoteDrafts.subtract(localChildrenNotSent); return remoteDrafts; } - - /* - * To test, start a server: - * $ hg --config web.allow_push=* --config web.push_ssl=False --config server.validate=True --debug serve - */ - public static void main(String[] args) throws Exception { - final HgLookup hgLookup = new HgLookup(); - HgRepository r = hgLookup.detect("/home/artem/hg/test-phases/"); - HgRemoteRepository rr = hgLookup.detect(new URL("http://localhost:8000/")); - new HgPushCommand(r).destination(rr).execute(); - } } diff -r cd77bf51b562 -r 629a7370554c src/org/tmatesoft/hg/internal/RepositoryComparator.java --- a/src/org/tmatesoft/hg/internal/RepositoryComparator.java Tue Jul 02 23:21:16 2013 +0200 +++ b/src/org/tmatesoft/hg/internal/RepositoryComparator.java Wed Jul 03 14:38:30 2013 +0200 @@ -38,7 +38,6 @@ import org.tmatesoft.hg.repo.HgRemoteRepository; import org.tmatesoft.hg.repo.HgRemoteRepository.Range; import org.tmatesoft.hg.repo.HgRemoteRepository.RemoteBranch; -import org.tmatesoft.hg.repo.HgRuntimeException; import org.tmatesoft.hg.util.CancelSupport; import org.tmatesoft.hg.util.CancelledException; import org.tmatesoft.hg.util.ProgressSupport; @@ -113,45 +112,6 @@ } } - /** - * Similar to @link {@link #getLocalOnlyRevisions()}, use this one if you need access to changelog entry content, not - * only its revision number. - * @param inspector delegate to analyze changesets, shall not be null - */ - public void visitLocalOnlyRevisions(HgChangelog.Inspector inspector) throws HgRuntimeException { - if (inspector == null) { - throw new IllegalArgumentException(); - } - // one can use localRepo.childrenOf(getCommon()) and then iterate over nodeids, but there seems to be - // another approach to get all changes after common: - // find index of earliest revision, and report all that were later - final HgChangelog changelog = localRepo.getRepo().getChangelog(); - int earliestRevision = Integer.MAX_VALUE; - List commonKnown = getCommon(); - for (Nodeid n : commonKnown) { - if (!localRepo.hasChildren(n)) { - // there might be (old) nodes, known both locally and remotely, with no children - // hence, we don't need to consider their local revision number - continue; - } - int lr = changelog.getRevisionIndex(n); - if (lr < earliestRevision) { - earliestRevision = lr; - } - } - if (earliestRevision == Integer.MAX_VALUE) { - // either there are no common nodes (known locally and at remote) - // or no local children found (local is up to date). In former case, perhaps I shall bit return silently, - // but check for possible wrong repo comparison (hs says 'repository is unrelated' if I try to - // check in/out for a repo that has no common nodes. - return; - } - if (earliestRevision < 0 || earliestRevision >= changelog.getLastRevision()) { - throw new HgInvalidStateException(String.format("Invalid index of common known revision: %d in total of %d", earliestRevision, 1+changelog.getLastRevision())); - } - changelog.range(earliestRevision+1, changelog.getLastRevision(), inspector); - } - private List findCommonWithRemote() throws HgRemoteConnectionException { remoteHeads = remoteRepo.heads(); LinkedList resultCommon = new LinkedList(); // these remotes are known in local diff -r cd77bf51b562 -r 629a7370554c src/org/tmatesoft/hg/internal/RevisionSet.java --- a/src/org/tmatesoft/hg/internal/RevisionSet.java Tue Jul 02 23:21:16 2013 +0200 +++ b/src/org/tmatesoft/hg/internal/RevisionSet.java Wed Jul 03 14:38:30 2013 +0200 @@ -19,6 +19,7 @@ import static org.tmatesoft.hg.repo.HgRepository.NO_REVISION; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashSet; @@ -41,6 +42,10 @@ private final Set elements; + public RevisionSet(Nodeid... revisions) { + this(revisions == null ? null : Arrays.asList(revisions)); + } + public RevisionSet(Collection revisions) { this(revisions == null ? new HashSet() : new HashSet(revisions)); } diff -r cd77bf51b562 -r 629a7370554c src/org/tmatesoft/hg/repo/HgParentChildMap.java --- a/src/org/tmatesoft/hg/repo/HgParentChildMap.java Tue Jul 02 23:21:16 2013 +0200 +++ b/src/org/tmatesoft/hg/repo/HgParentChildMap.java Wed Jul 03 14:38:30 2013 +0200 @@ -112,6 +112,7 @@ heads = new BitSet(revisionCount); revlog.indexWalk(0, TIP, this); Arrays.sort(sorted); + // FIXME use ArrayHelper instead sorted2natural = new int[revisionCount]; for (int i = 0; i < revisionCount; i++) { Nodeid n = sequential[i]; @@ -218,11 +219,14 @@ * @return revisions that have supplied revision as their immediate parent */ public List directChildren(Nodeid nid) { - LinkedList result = new LinkedList(); int x = Arrays.binarySearch(sorted, nid); assertSortedIndex(x); nid = sorted[x]; // canonical instance int start = sorted2natural[x]; + if (!hasChildren(start)) { + return Collections.emptyList(); + } + LinkedList result = new LinkedList(); for (int i = start + 1; i < sequential.length; i++) { if (nid == firstParent[i] || nid == secondParent[i]) { result.add(sequential[i]); @@ -291,6 +295,9 @@ int index = 0; do { index = heads.nextClearBit(index); + // nextClearBit(length-1) gives length when bit is set, + // however, last revision can't be a parent of any other, and + // the last bit would be always 0, and no AIOOBE result.add(sequential[index]); index++; } while (index < sequential.length); diff -r cd77bf51b562 -r 629a7370554c test/org/tmatesoft/hg/test/HgServer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/org/tmatesoft/hg/test/HgServer.java Wed Jul 03 14:38:30 2013 +0200 @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2013 TMate Software Ltd + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * For information on how to redistribute this software under + * the terms of a license other than GNU General Public License + * contact TMate Software at support@hg4j.com + */ +package org.tmatesoft.hg.test; + +import java.io.File; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; + +/** + * Wraps hg server + * + * @author Artem Tikhomirov + * @author TMate Software Ltd. + */ +class HgServer { + private Process serverProcess; + private boolean publish = true; + + public HgServer publishing(boolean pub) { + publish = pub; + return this; + } + + public HgServer start(File dir) throws IOException, InterruptedException { + if (serverProcess != null) { + stop(); + } + List cmdline = new ArrayList(); + cmdline.add("hg"); + cmdline.add("--config"); + cmdline.add("web.allow_push=*"); + cmdline.add("--config"); + cmdline.add("web.push_ssl=False"); + cmdline.add("--config"); + cmdline.add("server.validate=True"); + cmdline.add("--config"); + cmdline.add(String.format("web.port=%d", port())); + if (!publish) { + cmdline.add("--config"); + cmdline.add("phases.publish=False"); + } + cmdline.add("serve"); + serverProcess = new ProcessBuilder(cmdline).directory(dir).start(); + Thread.sleep(500); + return this; + } + + public URL getURL() throws MalformedURLException { + return new URL(String.format("http://localhost:%d/", port())); + } + + public int port() { + return 9090; + } + + public void stop() { + if (serverProcess == null) { + return; + } + // if Process#destroy() doesn't perform well with scripts and child processes + // may need to write server pid to a file and send a kill here + serverProcess.destroy(); + serverProcess = null; + } +} \ No newline at end of file diff -r cd77bf51b562 -r 629a7370554c test/org/tmatesoft/hg/test/RepoUtils.java --- a/test/org/tmatesoft/hg/test/RepoUtils.java Tue Jul 02 23:21:16 2013 +0200 +++ b/test/org/tmatesoft/hg/test/RepoUtils.java Wed Jul 03 14:38:30 2013 +0200 @@ -34,6 +34,7 @@ import org.tmatesoft.hg.core.HgException; import org.tmatesoft.hg.core.HgInitCommand; +import org.tmatesoft.hg.core.Nodeid; import org.tmatesoft.hg.internal.FileUtils; import org.tmatesoft.hg.internal.StreamLogFacility; import org.tmatesoft.hg.repo.HgRepository; @@ -190,4 +191,12 @@ } dest.delete(); } + + static Nodeid[] allRevisions(HgRepository repo) { + Nodeid[] allRevs = new Nodeid[repo.getChangelog().getRevisionCount()]; + for (int i = 0; i < allRevs.length; i++) { + allRevs[i] = repo.getChangelog().getRevision(i); + } + return allRevs; + } } diff -r cd77bf51b562 -r 629a7370554c test/org/tmatesoft/hg/test/TestIncoming.java --- a/test/org/tmatesoft/hg/test/TestIncoming.java Tue Jul 02 23:21:16 2013 +0200 +++ b/test/org/tmatesoft/hg/test/TestIncoming.java Wed Jul 03 14:38:30 2013 +0200 @@ -115,8 +115,8 @@ HashSet set = new HashSet(liteResult); for (Nodeid nid : expected) { boolean removed = set.remove(nid); - errorCollector.checkThat(what + " Missing " + nid.shortNotation() + " in HgIncomingCommand.execLite result", removed, equalTo(true)); + errorCollector.checkThat(what + " Missing " + nid.shortNotation() + " in execLite result", removed, equalTo(true)); } - errorCollector.checkThat(what + " Superfluous cset reported by HgIncomingCommand.execLite", set.isEmpty(), equalTo(true)); + errorCollector.checkThat(what + " Superfluous cset reported by execLite", set.isEmpty(), equalTo(true)); } } diff -r cd77bf51b562 -r 629a7370554c test/org/tmatesoft/hg/test/TestOutgoing.java --- a/test/org/tmatesoft/hg/test/TestOutgoing.java Tue Jul 02 23:21:16 2013 +0200 +++ b/test/org/tmatesoft/hg/test/TestOutgoing.java Wed Jul 03 14:38:30 2013 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 TMate Software Ltd + * Copyright (c) 2011-2013 TMate Software Ltd * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,19 +16,23 @@ */ package org.tmatesoft.hg.test; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + import java.io.File; -import java.io.FileWriter; -import java.io.IOException; import java.util.List; import org.junit.Assert; import org.junit.Rule; import org.junit.Test; +import org.tmatesoft.hg.core.HgCheckoutCommand; +import org.tmatesoft.hg.core.HgCommitCommand; import org.tmatesoft.hg.core.HgLogCommand; import org.tmatesoft.hg.core.HgOutgoingCommand; import org.tmatesoft.hg.core.Nodeid; import org.tmatesoft.hg.repo.HgLookup; import org.tmatesoft.hg.repo.HgRemoteRepository; +import org.tmatesoft.hg.repo.HgRepository; /** * @@ -71,10 +75,10 @@ TestIncoming.report(collector, outParser, liteResult, errorCollector); // File f = new File(dest, "Test.txt"); - append(f, "1"); + RepoUtils.createFile(f, "1"); eh0.run("hg", "add"); eh0.run("hg", "commit", "-m", "1"); - append(f, "2"); + RepoUtils.modifyFileAppend(f, "2"); eh0.run("hg", "commit", "-m", "2"); // cmd = new HgOutgoingCommand(lookup.detect(dest)).against(hgRemote); @@ -85,10 +89,41 @@ TestIncoming.report(collector, outParser, liteResult, errorCollector); } } - - static void append(File f, String s) throws IOException { - FileWriter fw = new FileWriter(f); - fw.append(s); - fw.close(); + + /** + * Issue 47: Incorrect set of outgoing changes when revision spins off prior to common revision of local and remote repos + */ + @Test + public void testOutgoingPreceedsCommon() throws Exception { + File srcRepoLoc = RepoUtils.cloneRepoToTempLocation("test-annotate", "test-outgoing-src", false); + File dstRepoLoc = RepoUtils.cloneRepoToTempLocation("test-annotate", "test-outgoing-dst", false); + File f1 = new File(srcRepoLoc, "file1"); + assertTrue("[sanity]", f1.canWrite()); + HgServer server = new HgServer().start(dstRepoLoc); + try { + final HgLookup hgLookup = new HgLookup(); + final HgRepository srcRepo = hgLookup.detect(srcRepoLoc); + final HgRemoteRepository dstRemote = hgLookup.detect(server.getURL()); + new HgCheckoutCommand(srcRepo).changeset(6).clean(true).execute(); + assertEquals("[sanity]", "with-merge", srcRepo.getWorkingCopyBranchName()); + RepoUtils.modifyFileAppend(f1, "change1"); + new HgCommitCommand(srcRepo).message("Commit 1").execute(); + new HgCheckoutCommand(srcRepo).changeset(5).clean(true).execute(); + assertEquals("[sanity]", "no-merge", srcRepo.getWorkingCopyBranchName()); + RepoUtils.modifyFileAppend(f1, "change2"); + new HgCommitCommand(srcRepo).message("Commit 2").execute(); + // + HgOutgoingCommand cmd = new HgOutgoingCommand(srcRepo).against(dstRemote); + LogOutputParser outParser = new LogOutputParser(true); + ExecHelper eh = new ExecHelper(outParser, srcRepoLoc); + HgLogCommand.CollectHandler collector = new HgLogCommand.CollectHandler(); + // + List liteResult = cmd.executeLite(); + cmd.executeFull(collector); + eh.run("hg", "outgoing", "--debug", dstRemote.getLocation()); + TestIncoming.report(collector, outParser, liteResult, errorCollector); + } finally { + server.stop(); + } } } diff -r cd77bf51b562 -r 629a7370554c test/org/tmatesoft/hg/test/TestPush.java --- a/test/org/tmatesoft/hg/test/TestPush.java Tue Jul 02 23:21:16 2013 +0200 +++ b/test/org/tmatesoft/hg/test/TestPush.java Wed Jul 03 14:38:30 2013 +0200 @@ -20,10 +20,6 @@ import static org.tmatesoft.hg.repo.HgRepository.TIP; import java.io.File; -import java.io.IOException; -import java.net.MalformedURLException; -import java.net.URL; -import java.util.ArrayList; import java.util.List; import org.junit.Rule; @@ -383,62 +379,9 @@ } } - private void checkRepositoriesAreSame(HgRepository srcRepo, HgRepository dstRepo) { errorCollector.assertEquals(srcRepo.getChangelog().getRevisionCount(), dstRepo.getChangelog().getRevisionCount()); errorCollector.assertEquals(srcRepo.getChangelog().getRevision(0), dstRepo.getChangelog().getRevision(0)); errorCollector.assertEquals(srcRepo.getChangelog().getRevision(TIP), dstRepo.getChangelog().getRevision(TIP)); } - - static class HgServer { - private Process serverProcess; - private boolean publish = true; - - public HgServer publishing(boolean pub) { - publish = pub; - return this; - } - - public HgServer start(File dir) throws IOException, InterruptedException { - if (serverProcess != null) { - stop(); - } - List cmdline = new ArrayList(); - cmdline.add("hg"); - cmdline.add("--config"); - cmdline.add("web.allow_push=*"); - cmdline.add("--config"); - cmdline.add("web.push_ssl=False"); - cmdline.add("--config"); - cmdline.add("server.validate=True"); - cmdline.add("--config"); - cmdline.add(String.format("web.port=%d", port())); - if (!publish) { - cmdline.add("--config"); - cmdline.add("phases.publish=False"); - } - cmdline.add("serve"); - serverProcess = new ProcessBuilder(cmdline).directory(dir).start(); - Thread.sleep(500); - return this; - } - - public URL getURL() throws MalformedURLException { - return new URL(String.format("http://localhost:%d/", port())); - } - - public int port() { - return 9090; - } - - public void stop() { - if (serverProcess == null) { - return; - } - // if Process#destroy() doesn't perform well with scripts and child processes - // may need to write server pid to a file and send a kill here - serverProcess.destroy(); - serverProcess = null; - } - } } diff -r cd77bf51b562 -r 629a7370554c test/org/tmatesoft/hg/test/TestRevisionMaps.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/org/tmatesoft/hg/test/TestRevisionMaps.java Wed Jul 03 14:38:30 2013 +0200 @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2013 TMate Software Ltd + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * For information on how to redistribute this software under + * the terms of a license other than GNU General Public License + * contact TMate Software at support@hg4j.com + */ +package org.tmatesoft.hg.test; + +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; + +import org.junit.Rule; +import org.junit.Test; +import org.tmatesoft.hg.core.HgException; +import org.tmatesoft.hg.core.Nodeid; +import org.tmatesoft.hg.repo.HgChangelog; +import org.tmatesoft.hg.repo.HgParentChildMap; +import org.tmatesoft.hg.repo.HgRepository; + +/** + * + * @author Artem Tikhomirov + * @author TMate Software Ltd. + */ +public class TestRevisionMaps { + + @Rule + public ErrorCollectorExt errorCollector = new ErrorCollectorExt(); + + @Test + public void testParentChildMap() throws HgException { + final HgRepository repo = Configuration.get().find("test-annotate"); + Nodeid[] allRevs = RepoUtils.allRevisions(repo); + HgParentChildMap parentHelper = new HgParentChildMap(repo.getChangelog()); + parentHelper.init(); + errorCollector.assertEquals(Arrays.asList(allRevs), parentHelper.all()); + for (Nodeid n : allRevs) { + errorCollector.assertTrue(parentHelper.knownNode(n)); + // parents + final Nodeid p1 = parentHelper.safeFirstParent(n); + final Nodeid p2 = parentHelper.safeSecondParent(n); + errorCollector.assertFalse(p1 == null); + errorCollector.assertFalse(p2 == null); + errorCollector.assertEquals(p1.isNull() ? null : p1, parentHelper.firstParent(n)); + errorCollector.assertEquals(p2.isNull() ? null : p2, parentHelper.secondParent(n)); + HashSet parents = new HashSet(); + boolean modified = parentHelper.appendParentsOf(n, parents); + errorCollector.assertEquals(p1.isNull() && p2.isNull(), !modified); + HashSet cp = new HashSet(); + cp.add(parentHelper.firstParent(n)); + cp.add(parentHelper.secondParent(n)); + cp.remove(null); + errorCollector.assertEquals(cp, parents); + modified = parentHelper.appendParentsOf(n, parents); + errorCollector.assertFalse(modified); + // + // isChild, hasChildren, childrenOf, directChildren + if (!p1.isNull()) { + errorCollector.assertTrue(parentHelper.isChild(p1, n)); + errorCollector.assertTrue(parentHelper.hasChildren(p1)); + errorCollector.assertTrue(parentHelper.childrenOf(Collections.singleton(p1)).contains(n)); + errorCollector.assertTrue(parentHelper.directChildren(p1).contains(n)); + } + if (!p2.isNull()) { + errorCollector.assertTrue(parentHelper.isChild(p2, n)); + errorCollector.assertTrue(parentHelper.hasChildren(p2)); + errorCollector.assertTrue(parentHelper.childrenOf(Collections.singleton(p2)).contains(n)); + errorCollector.assertTrue(parentHelper.directChildren(p2).contains(n)); + } + errorCollector.assertFalse(parentHelper.isChild(n, p1)); + errorCollector.assertFalse(parentHelper.isChild(n, p2)); + // + + } + // heads + errorCollector.assertEquals(Arrays.asList(allRevs[7], allRevs[9]), parentHelper.heads()); + // isChild + errorCollector.assertTrue(parentHelper.isChild(allRevs[1], allRevs[9])); + errorCollector.assertTrue(parentHelper.isChild(allRevs[0], allRevs[7])); + errorCollector.assertFalse(parentHelper.isChild(allRevs[4], allRevs[7])); + errorCollector.assertFalse(parentHelper.isChild(allRevs[2], allRevs[6])); + // childrenOf + errorCollector.assertEquals(Arrays.asList(allRevs[7]), parentHelper.childrenOf(Collections.singleton(allRevs[5]))); + errorCollector.assertEquals(Arrays.asList(allRevs[8], allRevs[9]), parentHelper.childrenOf(Arrays.asList(allRevs[4], allRevs[6]))); + errorCollector.assertEquals(Arrays.asList(allRevs[6], allRevs[8], allRevs[9]), parentHelper.childrenOf(Collections.singleton(allRevs[3]))); + // directChildren + errorCollector.assertEquals(Arrays.asList(allRevs[2], allRevs[3]), parentHelper.directChildren(allRevs[1])); + errorCollector.assertEquals(Arrays.asList(allRevs[8]), parentHelper.directChildren(allRevs[6])); + errorCollector.assertEquals(Collections.emptyList(), parentHelper.directChildren(allRevs[7])); + } + +} diff -r cd77bf51b562 -r 629a7370554c test/org/tmatesoft/hg/test/TestRevisionSet.java --- a/test/org/tmatesoft/hg/test/TestRevisionSet.java Tue Jul 02 23:21:16 2013 +0200 +++ b/test/org/tmatesoft/hg/test/TestRevisionSet.java Wed Jul 03 14:38:30 2013 +0200 @@ -16,8 +16,6 @@ */ package org.tmatesoft.hg.test; -import java.util.Arrays; - import org.junit.Rule; import org.junit.Test; import org.tmatesoft.hg.core.Nodeid; @@ -42,13 +40,20 @@ Nodeid n2 = Nodeid.fromAscii("3b7d51ed4c65082f9235e3459e282d7ff723aa97"); Nodeid n3 = Nodeid.fromAscii("14dac192aa262feb8ff6645a102648498483a188"); Nodeid n4 = Nodeid.fromAscii("1deea2f332183c947937f6df988c2c6417efc217"); - RevisionSet a = rs(n1, n2, n3); - RevisionSet b = rs(n3, n4); - RevisionSet union_ab = rs(n1, n2, n3, n4); - RevisionSet intersect_ab = rs(n3); - RevisionSet subtract_ab = rs(n1, n2); - RevisionSet subtract_ba = rs(n4); - RevisionSet symDiff_ab = rs(n1, n2, n4); + Nodeid[] nodes = { n1, n2, n3 }; + RevisionSet a = new RevisionSet(nodes); + Nodeid[] nodes1 = { n3, n4 }; + RevisionSet b = new RevisionSet(nodes1); + Nodeid[] nodes2 = { n1, n2, n3, n4 }; + RevisionSet union_ab = new RevisionSet(nodes2); + Nodeid[] nodes3 = { n3 }; + RevisionSet intersect_ab = new RevisionSet(nodes3); + Nodeid[] nodes4 = { n1, n2 }; + RevisionSet subtract_ab = new RevisionSet(nodes4); + Nodeid[] nodes5 = { n4 }; + RevisionSet subtract_ba = new RevisionSet(nodes5); + Nodeid[] nodes6 = { n1, n2, n4 }; + RevisionSet symDiff_ab = new RevisionSet(nodes6); errorCollector.assertEquals(union_ab, a.union(b)); errorCollector.assertEquals(union_ab, b.union(a)); @@ -58,67 +63,81 @@ errorCollector.assertEquals(subtract_ba, b.subtract(a)); errorCollector.assertEquals(symDiff_ab, a.symmetricDifference(b)); errorCollector.assertEquals(symDiff_ab, b.symmetricDifference(a)); - errorCollector.assertTrue(rs(n1, n2, n4).equals(rs(n4, n1, n2))); - errorCollector.assertTrue(rs().equals(rs())); - errorCollector.assertFalse(rs(n1).equals(rs(n2))); + Nodeid[] nodes7 = { n1, n2, n4 }; + Nodeid[] nodes8 = { n4, n1, n2 }; + errorCollector.assertTrue(new RevisionSet(nodes7).equals(new RevisionSet(nodes8))); + Nodeid[] nodes9 = {}; + Nodeid[] nodes10 = {}; + errorCollector.assertTrue(new RevisionSet(nodes9).equals(new RevisionSet(nodes10))); + Nodeid[] nodes11 = { n1 }; + Nodeid[] nodes12 = { n2 }; + errorCollector.assertFalse(new RevisionSet(nodes11).equals(new RevisionSet(nodes12))); } @Test public void testRootsAndHeads() throws Exception { final HgRepository repo = Configuration.get().find("test-annotate"); - Nodeid[] allRevs = allRevisions(repo); + Nodeid[] allRevs = RepoUtils.allRevisions(repo); HgParentChildMap parentHelper = new HgParentChildMap(repo.getChangelog()); parentHelper.init(); - final RevisionSet complete = rs(allRevs); + final RevisionSet complete = new RevisionSet(allRevs); + Nodeid[] nodes = { allRevs[0] }; // roots - errorCollector.assertEquals(rs(allRevs[0]), complete.roots(parentHelper)); - RevisionSet fromR2 = complete.subtract(rs(allRevs[0], allRevs[1])); - RevisionSet fromR3 = complete.subtract(rs(allRevs[0], allRevs[1], allRevs[2])); - errorCollector.assertEquals(rs(allRevs[2], allRevs[3]), fromR2.roots(parentHelper)); - errorCollector.assertEquals(rs(allRevs[3], allRevs[4], allRevs[5]), fromR3.roots(parentHelper)); + errorCollector.assertEquals(new RevisionSet(nodes), complete.roots(parentHelper)); + Nodeid[] nodes1 = { allRevs[0], allRevs[1] }; + RevisionSet fromR2 = complete.subtract(new RevisionSet(nodes1)); + Nodeid[] nodes2 = { allRevs[0], allRevs[1], allRevs[2] }; + RevisionSet fromR3 = complete.subtract(new RevisionSet(nodes2)); + Nodeid[] nodes3 = { allRevs[2], allRevs[3] }; + errorCollector.assertEquals(new RevisionSet(nodes3), fromR2.roots(parentHelper)); + Nodeid[] nodes4 = { allRevs[3], allRevs[4], allRevs[5] }; + errorCollector.assertEquals(new RevisionSet(nodes4), fromR3.roots(parentHelper)); + Nodeid[] nodes5 = { allRevs[9], allRevs[7] }; // heads - errorCollector.assertEquals(rs(allRevs[9], allRevs[7]), complete.heads(parentHelper)); - RevisionSet toR7 = complete.subtract(rs(allRevs[9], allRevs[8])); - errorCollector.assertEquals(rs(allRevs[7], allRevs[6], allRevs[4]), toR7.heads(parentHelper)); - RevisionSet withoutNoMergeBranch = toR7.subtract(rs(allRevs[5], allRevs[7])); - errorCollector.assertEquals(rs(allRevs[6], allRevs[4]), withoutNoMergeBranch.heads(parentHelper)); + errorCollector.assertEquals(new RevisionSet(nodes5), complete.heads(parentHelper)); + Nodeid[] nodes6 = { allRevs[9], allRevs[8] }; + RevisionSet toR7 = complete.subtract(new RevisionSet(nodes6)); + Nodeid[] nodes7 = { allRevs[7], allRevs[6], allRevs[4] }; + errorCollector.assertEquals(new RevisionSet(nodes7), toR7.heads(parentHelper)); + Nodeid[] nodes8 = { allRevs[5], allRevs[7] }; + RevisionSet withoutNoMergeBranch = toR7.subtract(new RevisionSet(nodes8)); + Nodeid[] nodes9 = { allRevs[6], allRevs[4] }; + errorCollector.assertEquals(new RevisionSet(nodes9), withoutNoMergeBranch.heads(parentHelper)); errorCollector.assertEquals(complete.heads(parentHelper), complete.heads(parentHelper).heads(parentHelper)); } @Test public void testAncestorsAndChildren() throws Exception { final HgRepository repo = Configuration.get().find("test-annotate"); - Nodeid[] allRevs = allRevisions(repo); + Nodeid[] allRevs = RepoUtils.allRevisions(repo); HgParentChildMap parentHelper = new HgParentChildMap(repo.getChangelog()); parentHelper.init(); - final RevisionSet complete = rs(allRevs); + final RevisionSet complete = new RevisionSet(allRevs); + Nodeid[] nodes = {}; // children - errorCollector.assertTrue(rs().children(parentHelper).isEmpty()); - errorCollector.assertEquals(rs(allRevs[8], allRevs[9]), rs(allRevs[4]).children(parentHelper)); + errorCollector.assertTrue(new RevisionSet(nodes).children(parentHelper).isEmpty()); + Nodeid[] nodes1 = { allRevs[8], allRevs[9] }; + Nodeid[] nodes2 = { allRevs[4] }; + errorCollector.assertEquals(new RevisionSet(nodes1), new RevisionSet(nodes2).children(parentHelper)); + Nodeid[] nodes3 = { allRevs[8], allRevs[9], allRevs[4], allRevs[5], allRevs[7] }; // default branch and no-merge branch both from r2 - RevisionSet s1 = rs(allRevs[8], allRevs[9], allRevs[4], allRevs[5], allRevs[7]); - errorCollector.assertEquals(s1, rs(allRevs[2]).children(parentHelper)); + RevisionSet s1 = new RevisionSet(nodes3); + Nodeid[] nodes4 = { allRevs[2] }; + errorCollector.assertEquals(s1, new RevisionSet(nodes4).children(parentHelper)); + Nodeid[] nodes5 = { allRevs[0], allRevs[1] }; // ancestors - RevisionSet fromR2 = complete.subtract(rs(allRevs[0], allRevs[1])); + RevisionSet fromR2 = complete.subtract(new RevisionSet(nodes5)); + Nodeid[] nodes6 = { allRevs[9], allRevs[5], allRevs[7], allRevs[8] }; // no-merge branch and r9 are not in ancestors of r8 (as well as r8 itself) - RevisionSet s3 = fromR2.subtract(rs(allRevs[9], allRevs[5], allRevs[7], allRevs[8])); - errorCollector.assertEquals(s3, fromR2.ancestors(rs(allRevs[8]), parentHelper)); + RevisionSet s3 = fromR2.subtract(new RevisionSet(nodes6)); + Nodeid[] nodes7 = { allRevs[8] }; + errorCollector.assertEquals(s3, fromR2.ancestors(new RevisionSet(nodes7), parentHelper)); + Nodeid[] nodes8 = { allRevs[5], allRevs[7] }; // ancestors of no-merge branch - RevisionSet branchNoMerge = rs(allRevs[5], allRevs[7]); - errorCollector.assertEquals(rs(allRevs[0], allRevs[1], allRevs[2]), complete.ancestors(branchNoMerge, parentHelper)); - errorCollector.assertEquals(rs(allRevs[2]), fromR2.ancestors(branchNoMerge, parentHelper)); - } - - private static Nodeid[] allRevisions(HgRepository repo) { - Nodeid[] allRevs = new Nodeid[repo.getChangelog().getRevisionCount()]; - for (int i = 0; i < allRevs.length; i++) { - allRevs[i] = repo.getChangelog().getRevision(i); - } - return allRevs; - } - - - private static RevisionSet rs(Nodeid... nodes) { - return new RevisionSet(Arrays.asList(nodes)); + RevisionSet branchNoMerge = new RevisionSet(nodes8); + Nodeid[] nodes9 = { allRevs[0], allRevs[1], allRevs[2] }; + errorCollector.assertEquals(new RevisionSet(nodes9), complete.ancestors(branchNoMerge, parentHelper)); + Nodeid[] nodes10 = { allRevs[2] }; + errorCollector.assertEquals(new RevisionSet(nodes10), fromR2.ancestors(branchNoMerge, parentHelper)); } }