diff src/org/tmatesoft/hg/internal/RepositoryComparator.java @ 192:e5407b5a586a

Incoming and Outgoing commands are alive
author Artem Tikhomirov <tikhomirov.artem@gmail.com>
date Fri, 15 Apr 2011 03:17:03 +0200
parents ec1820f64d2b
children 706bcc7cfee4
line wrap: on
line diff
--- a/src/org/tmatesoft/hg/internal/RepositoryComparator.java	Thu Apr 14 19:53:31 2011 +0200
+++ b/src/org/tmatesoft/hg/internal/RepositoryComparator.java	Fri Apr 15 03:17:03 2011 +0200
@@ -18,11 +18,13 @@
 
 import static org.tmatesoft.hg.core.Nodeid.NULL;
 
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.ListIterator;
 import java.util.Map;
 import java.util.Map.Entry;
 
@@ -59,6 +61,12 @@
 		cancelSupport.checkCancelled();
 		progressSupport.start(10);
 		common = Collections.unmodifiableList(findCommonWithRemote());
+		// sanity check
+		for (Nodeid n : common) {
+			if (!localRepo.knownNode(n)) {
+				throw new HgBadStateException("Unknown node reported as common:" + n);
+			}
+		}
 		progressSupport.done();
 		return this;
 	}
@@ -69,6 +77,45 @@
 		}
 		return common;
 	}
+	
+	/**
+	 * @return revisions that are children of common entries, i.e. revisions that are present on the local server and not on remote.
+	 */
+	public List<Nodeid> getLocalOnlyRevisions() {
+		return localRepo.childrenOf(getCommon());
+	}
+	
+	/**
+	 * 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 <code>null</code>
+	 */
+	public void visitLocalOnlyRevisions(HgChangelog.Inspector inspector) {
+		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<Nodeid> 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.getLocalRevision(n);
+			if (lr < earliestRevision) {
+				earliestRevision = lr;
+			}
+		}
+		if (earliestRevision < 0 || earliestRevision >= changelog.getLastRevision()) {
+			throw new HgBadStateException(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<Nodeid> findCommonWithRemote() throws HgException {
 		List<Nodeid> remoteHeads = remoteRepo.heads();
@@ -403,4 +450,49 @@
 		}
 		return fromRootToHead;
 	}
+
+	/**
+	 *  returns in order from branch root to head
+	 *  for a non-empty BranchChain, shall return modifiable list
+	 */
+	public List<Nodeid> visitBranches(BranchChain bc) throws HgException {
+		if (bc == null) {
+			return Collections.emptyList();
+		}
+		List<Nodeid> mine = completeBranch(bc.branchRoot, bc.branchHead);
+		if (bc.isTerminal()) {
+			return mine;
+		}
+		List<Nodeid> parentBranch1 = visitBranches(bc.p1);
+		List<Nodeid> parentBranch2 = visitBranches(bc.p2);
+		// merge
+		LinkedList<Nodeid> merged = new LinkedList<Nodeid>();
+		ListIterator<Nodeid> i1 = parentBranch1.listIterator(), i2 = parentBranch2.listIterator();
+		while (i1.hasNext() && i2.hasNext()) {
+			Nodeid n1 = i1.next();
+			Nodeid n2 = i2.next();
+			if (n1.equals(n2)) {
+				merged.addLast(n1);
+			} else {
+				// first different => add both, and continue adding both tails sequentially 
+				merged.add(n2);
+				merged.add(n1);
+				break;
+			}
+		}
+		// copy rest of second parent branch
+		while (i2.hasNext()) {
+			merged.add(i2.next());
+		}
+		// copy rest of first parent branch
+		while (i1.hasNext()) {
+			merged.add(i1.next());
+		}
+		//
+		ArrayList<Nodeid> rv = new ArrayList<Nodeid>(mine.size() + merged.size());
+		rv.addAll(merged);
+		rv.addAll(mine);
+		return rv;
+	}
+
 }