# HG changeset patch # User Artem Tikhomirov # Date 1317205101 -7200 # Node ID 8952f89be195e2c62f42b46fafb0b00d0b4288c2 # Parent fb74133d20253f4af5512e0eed58c04edbe4841c Allow to query specific branch heads if they are closed diff -r fb74133d2025 -r 8952f89be195 src/org/tmatesoft/hg/repo/HgBranches.java --- a/src/org/tmatesoft/hg/repo/HgBranches.java Tue Sep 27 06:34:54 2011 +0200 +++ b/src/org/tmatesoft/hg/repo/HgBranches.java Wed Sep 28 12:18:21 2011 +0200 @@ -22,6 +22,7 @@ import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; @@ -325,6 +326,7 @@ private List heads; private boolean closed; private final Nodeid start; + private List closedHeads; // subset of heads, those that bear 'closed' flag, or null if closed == true // XXX in fact, few but not all branchHeads might be closed, and isClosed for whole branch is not // possible to determine. @@ -349,6 +351,7 @@ // [0] tipmost, [1] tipmost open final Nodeid[] tipmost = new Nodeid[] {null, null}; final boolean[] allClosed = new boolean[] { true }; + final ArrayList _closedHeads = new ArrayList(heads.size()); clog.range(new HgChangelog.Inspector() { public void next(int revisionNumber, Nodeid nodeid, RawChangeset cset) { @@ -357,6 +360,8 @@ if (!"1".equals(cset.extras().get("close"))) { tipmost[1] = nodeid; allClosed[0] = false; + } else { + _closedHeads.add(nodeid); } } }, localCset); @@ -377,6 +382,13 @@ } } heads = Arrays.asList(outcome); + if (closed) { + // no need + closedHeads = null; + } else { + _closedHeads.trimToSize(); + closedHeads = _closedHeads; + } } public String getName() { @@ -388,9 +400,29 @@ public boolean isClosed() { return closed; } + + /** + * @return all heads for the branch, both open and closed, tip-most head first + */ public List getHeads() { return heads; } + + /** + * + * @param head one of revision from {@link #getHeads() heads} of this branch + * @return true if this particular head is closed + * @throws IllegalArgumentException if argument is not from {@link #getHeads() heads} of this branch + */ + public boolean isClosed(Nodeid head) { + if (!heads.contains(head)) { + throw new IllegalArgumentException(String.format("Revision %s does not belong to heads of %s branch", head, name), null); + } + if (closed) { + return true; + } + return closedHeads.contains(head); + } // public Nodeid getTip() { // } /*public*/ Nodeid getStart() { diff -r fb74133d2025 -r 8952f89be195 test/org/tmatesoft/hg/test/TestBranches.java --- a/test/org/tmatesoft/hg/test/TestBranches.java Tue Sep 27 06:34:54 2011 +0200 +++ b/test/org/tmatesoft/hg/test/TestBranches.java Wed Sep 28 12:18:21 2011 +0200 @@ -18,14 +18,22 @@ import static org.junit.Assert.*; -import org.junit.Assert; import org.junit.Test; +import org.tmatesoft.hg.core.Nodeid; import org.tmatesoft.hg.repo.HgBranches; import org.tmatesoft.hg.repo.HgBranches.BranchInfo; import org.tmatesoft.hg.repo.HgRepository; /** - * + *
+ * branches-1/create.bat:
+ * branch1 to have fork, two heads, both closed -- shall be recognized as closed
+ * branch2 to have fork, two heads, one closed  -- shall be recognized as active
+ * branch3 no active head						-- shall be recognized as inactive
+ * branch4 to fork, with 1 inactive and 1 active heads
+ * branch5 to be closed and reopened
+ * 
+ * * @author Artem Tikhomirov * @author TMate Software Ltd. */ @@ -69,4 +77,31 @@ assertEquals(1, b5.getHeads().size()); assertEquals("9cb6ad32b9074021356c38050e2aab6addba4393", b5.getHeads().get(0).toString()); } + + @Test + public void testBranchInfoClosedHeads() throws Exception{ + HgRepository repo = Configuration.get().find("branches-1"); + HgBranches branches = repo.getBranches(); + // branch1 - two closed heads + BranchInfo b1 = branches.getBranch("branch1"); + assertTrue(b1.isClosed(b1.getHeads().get(0))); + assertTrue(b1.isClosed(b1.getHeads().get(1))); + try { + b1.isClosed(Nodeid.fromAscii("9cb6ad32b9074021356c38050e2aab6addba4393")); + fail("Revision that doesn't belong to heads of the branch shall not be handled"); + } catch (IllegalArgumentException ex) { + // good + } + // + // branch2, one closed head + BranchInfo b2 = branches.getBranch("branch2"); + assertFalse(b2.isClosed(b2.getHeads().get(0))); + assertTrue(b2.isClosed(b2.getHeads().get(1))); + // + // branch5, closed and reopened, 1 open head + BranchInfo b5 = branches.getBranch("branch5"); + for (Nodeid h : b5.getHeads()) { + assertFalse(b5.isClosed(h)); + } + } }