Mercurial > hg4j
diff src/org/tmatesoft/hg/repo/HgDataFile.java @ 317:09628675bcee
Rework file history build approach to match rest of the API
author | Artem Tikhomirov <tikhomirov.artem@gmail.com> |
---|---|
date | Thu, 29 Sep 2011 03:20:28 +0200 |
parents | 971baa95fb07 |
children | d68dcb3b5f49 |
line wrap: on
line diff
--- a/src/org/tmatesoft/hg/repo/HgDataFile.java Wed Sep 28 13:09:16 2011 +0200 +++ b/src/org/tmatesoft/hg/repo/HgDataFile.java Thu Sep 29 03:20:28 2011 +0200 @@ -30,18 +30,15 @@ import java.util.Collection; import java.util.Collections; import java.util.List; -import java.util.NoSuchElementException; import org.tmatesoft.hg.core.HgDataStreamException; import org.tmatesoft.hg.core.HgException; import org.tmatesoft.hg.core.Nodeid; import org.tmatesoft.hg.internal.DataAccess; -import org.tmatesoft.hg.internal.Experimental; import org.tmatesoft.hg.internal.FilterByteChannel; import org.tmatesoft.hg.internal.FilterDataAccess; import org.tmatesoft.hg.internal.IntMap; import org.tmatesoft.hg.internal.RevlogStream; -import org.tmatesoft.hg.repo.HgChangelog.RawChangeset; import org.tmatesoft.hg.util.ByteChannel; import org.tmatesoft.hg.util.CancelSupport; import org.tmatesoft.hg.util.CancelledException; @@ -231,135 +228,117 @@ } } - @Experimental(reason="Investigate approaches to build complete file history log") - public interface HistoryWalker { - void next(); - boolean hasNext(); - Nodeid changesetRevision(); - RawChangeset changeset(); - boolean isFork(); - boolean isJoin(); - Pair<Nodeid, Nodeid> parentChangesets(); - Collection<Nodeid> childChangesets(); + private static class HistoryNode { + int changeset; + Nodeid cset; + HistoryNode parent1, parent2; + List<HistoryNode> children; + + HistoryNode(int cs, HistoryNode p1, HistoryNode p2) { + changeset = cs; + parent1 = p1; + parent2 = p2; + if (p1 != null) { + p1.addChild(this); + } + if (p2 != null) { + p2.addChild(this); + } + } + + Nodeid changesetRevision() { + assert cset != null : "we initialize all csets prior to use"; + return cset; + } + + void addChild(HistoryNode child) { + if (children == null) { + children = new ArrayList<HistoryNode>(2); + } + children.add(child); + } } - public HistoryWalker history() { - final boolean[] needsSorting = { false }; - class HistoryNode { - int changeset; - Nodeid cset; - HistoryNode parent1, parent2; - List<HistoryNode> children; - - public HistoryNode(int cs, HistoryNode p1, HistoryNode p2) { - changeset = cs; - parent1 = p1; - parent2 = p2; - if (p1 != null) { - p1.addChild(this); + public void history(HgChangelog.TreeInspector inspector) { + final CancelSupport cancelSupport = CancelSupport.Factory.get(inspector); + try { + final boolean[] needsSorting = { false }; + final HistoryNode[] completeHistory = new HistoryNode[getRevisionCount()]; + final int[] commitRevisions = new int[completeHistory.length]; + RevlogStream.Inspector insp = new RevlogStream.Inspector() { + public void next(int revisionNumber, int actualLen, int baseRevision, int linkRevision, int parent1Revision, int parent2Revision, byte[] nodeid, DataAccess data) { + if (revisionNumber > 0) { + if (commitRevisions[revisionNumber-1] > linkRevision) { + needsSorting[0] = true; + } + } + commitRevisions[revisionNumber] = linkRevision; + HistoryNode p1 = null, p2 = null; + if (parent1Revision != -1) { + p1 = completeHistory[parent1Revision]; + } + if (parent2Revision != -1) { + p2 = completeHistory[parent2Revision]; + } + completeHistory[revisionNumber] = new HistoryNode(linkRevision, p1, p2); } - if (p2 != null) { - p2.addChild(this); + }; + content.iterate(0, getLastRevision(), false, insp); + cancelSupport.checkCancelled(); + if (needsSorting[0]) { + Arrays.sort(commitRevisions); + } + // read changeset revisions at once (to avoid numerous changelog.getRevision reads) + // but just nodeids, not RawChangeset (changelog.iterate(data=false) + ArrayList<Nodeid> changesetRevisions = new ArrayList<Nodeid>(commitRevisions.length); + getRepo().getChangelog().getRevisionsInternal(changesetRevisions, commitRevisions); + cancelSupport.checkCancelled(); + // assign them to corresponding HistoryNodes + for (int i = 0; i < completeHistory.length; i++ ) { + final HistoryNode n = completeHistory[i]; + if (needsSorting[0]) { + int x = Arrays.binarySearch(commitRevisions, n.changeset); + assert x >= 0; + n.cset = changesetRevisions.get(x); + } else { + // commit revisions were not sorted, may use original index directly + n.cset = changesetRevisions.get(i); } } - - public Nodeid changesetRevision() { - if (cset == null) { - cset = getRepo().getChangelog().getRevision(changeset); - } - return cset; - } - - public void addChild(HistoryNode child) { - if (children == null) { - children = new ArrayList<HistoryNode>(2); - } - children.add(child); - } - } - final HistoryNode[] completeHistory = new HistoryNode[getRevisionCount()]; - final int[] commitRevisions = new int[completeHistory.length]; - RevlogStream.Inspector insp = new RevlogStream.Inspector() { - public void next(int revisionNumber, int actualLen, int baseRevision, int linkRevision, int parent1Revision, int parent2Revision, byte[] nodeid, DataAccess data) { - if (revisionNumber > 0) { - if (commitRevisions[revisionNumber-1] > linkRevision) { - needsSorting[0] = true; - } - } - HistoryNode p1 = null, p2 = null; - if (parent1Revision != -1) { - p1 = completeHistory[parent1Revision]; - } - if (parent2Revision != -1) { - p2 = completeHistory[parent2Revision]; - } - completeHistory[revisionNumber] = new HistoryNode(linkRevision, p1, p2); - } - }; - content.iterate(0, getLastRevision(), false, insp); - // XXX may read changeset revisions at once (to avoid numerous changelog.getRevision reads) - // but perhaps just nodeids, not RawChangeset (changelog.iterate(data=false) - // XXX sort completeHistory according to changeset numbers? - return new HistoryWalker() { - private int index = -1; - - public void next() { - if (!hasNext()) { - throw new NoSuchElementException(); - } - index++; - } - - public boolean hasNext() { - return index+1 < completeHistory.length; - } - - public Pair<Nodeid, Nodeid> parentChangesets() { + cancelSupport.checkCancelled(); + // XXX shall sort completeHistory according to changeset numbers? + for (int i = 0; i < completeHistory.length; i++ ) { + final HistoryNode n = completeHistory[i]; HistoryNode p; Nodeid p1, p2; - if ((p = completeHistory[index].parent1) != null) { + if ((p = n.parent1) != null) { p1 = p.changesetRevision(); } else { p1 = Nodeid.NULL; } - if ((p = completeHistory[index].parent2) != null) { + if ((p= n.parent2) != null) { p2 = p.changesetRevision(); } else { p2 = Nodeid.NULL; } - return new Pair<Nodeid, Nodeid>(p1, p2); - } - - public boolean isJoin() { - return completeHistory[index].parent1 != null && completeHistory[index].parent2 != null; - } - - public boolean isFork() { - HistoryNode n = completeHistory[index]; - return n.children != null && n.children.size() > 1; - } - - public Collection<Nodeid> childChangesets() { - HistoryNode n = completeHistory[index]; + final Pair<Nodeid, Nodeid> parentChangesets = new Pair<Nodeid, Nodeid>(p1, p2); + final List<Nodeid> childChangesets; if (n.children == null) { - return Collections.emptyList(); + childChangesets = Collections.emptyList(); + } else { + Nodeid[] revisions = new Nodeid[n.children.size()]; + int j = 0; + for (HistoryNode hn : n.children) { + revisions[j++] = hn.changesetRevision(); + } + childChangesets = Arrays.asList(revisions); } - ArrayList<Nodeid> rv = new ArrayList<Nodeid>(n.children.size()); - for (HistoryNode hn : n.children) { - rv.add(hn.changesetRevision()); - } - return rv; + inspector.next(n.changesetRevision(), parentChangesets, childChangesets); + cancelSupport.checkCancelled(); } - - public Nodeid changesetRevision() { - return completeHistory[index].changesetRevision(); - } - - public RawChangeset changeset() { - final int cs = completeHistory[index].changeset; - return getRepo().getChangelog().range(cs, cs).get(0); - } - }; + } catch (CancelledException ex) { + return; + } } public void history(HgChangelog.Inspector inspector) {