diff src/org/tmatesoft/hg/core/ChangesetTransformer.java @ 520:1ee452f31187

Experimental support for inverse direction history walking. Refactored/streamlined cancellation in HgLogCommand and down the stack
author Artem Tikhomirov <tikhomirov.artem@gmail.com>
date Fri, 21 Dec 2012 21:20:26 +0100
parents 1fc0da631200
children 6526d8adbc0f
line wrap: on
line diff
--- a/src/org/tmatesoft/hg/core/ChangesetTransformer.java	Thu Dec 20 20:21:59 2012 +0100
+++ b/src/org/tmatesoft/hg/core/ChangesetTransformer.java	Fri Dec 21 21:20:26 2012 +0100
@@ -18,6 +18,8 @@
 
 import java.util.Set;
 
+import org.tmatesoft.hg.internal.Lifecycle;
+import org.tmatesoft.hg.internal.LifecycleBridge;
 import org.tmatesoft.hg.internal.PathPool;
 import org.tmatesoft.hg.repo.HgChangelog;
 import org.tmatesoft.hg.repo.HgChangelog.RawChangeset;
@@ -37,14 +39,12 @@
  * @author Artem Tikhomirov
  * @author TMate Software Ltd.
  */
-/*package-local*/ class ChangesetTransformer implements HgChangelog.Inspector, Adaptable, CancelSupport {
+/*package-local*/ class ChangesetTransformer implements HgChangelog.Inspector, Adaptable {
 	private final HgChangesetHandler handler;
-	private final ProgressSupport progressHelper;
-	private final CancelSupport cancelHelper;
+	private final LifecycleBridge lifecycleBridge;
 	private final Transformation t;
 	private Set<String> branches;
 	private HgCallbackTargetException failure;
-	private CancelledException cancellation;
 
 	// repo and delegate can't be null, parent walker can
 	// ps and cs can't be null
@@ -58,11 +58,9 @@
 		HgStatusCollector statusCollector = new HgStatusCollector(hgRepo);
 		t = new Transformation(statusCollector, pw);
 		handler = delegate;
-		// we let HgChangelog#range deal with progress (pipe through getAdapter)
-		// but use own cancellation (which involves CallbackTargetException as well, and preserves original cancellation 
-		// exception in case clients care)
-		cancelHelper = cs;
-		progressHelper = ps;
+		// lifecycleBridge takes care of progress and cancellation, plus
+		// gives us explicit way to stop iteration (once HgCallbackTargetException) comes.
+		lifecycleBridge = new LifecycleBridge(ps, cs);
 	}
 	
 	public void next(int revisionNumber, Nodeid nodeid, RawChangeset cset) {
@@ -73,23 +71,21 @@
 		HgChangeset changeset = t.handle(revisionNumber, nodeid, cset);
 		try {
 			handler.cset(changeset);
-			cancelHelper.checkCancelled();
+			lifecycleBridge.nextStep();
 		} catch (HgCallbackTargetException ex) {
 			failure = ex.setRevision(nodeid).setRevisionIndex(revisionNumber);
-		} catch (CancelledException ex) {
-			cancellation = ex;
+			lifecycleBridge.stop();
 		}
 	}
 	
 	public void checkFailure() throws HgCallbackTargetException, CancelledException {
 		if (failure != null) {
 			HgCallbackTargetException toThrow = failure;
-			failure = null; // just in (otherwise unexpected) case this instance would get reused
 			throw toThrow;
 		}
-		if (cancellation != null) {
-			CancelledException toThrow = cancellation;
-			cancellation = null;
+		if (lifecycleBridge.isCancelled()) {
+			CancelledException toThrow = lifecycleBridge.getCancelOrigin();
+			assert toThrow != null;
 			throw toThrow;
 		}
 	}
@@ -121,18 +117,11 @@
 		}
 	}
 
-	public void checkCancelled() throws CancelledException {
-		if (failure != null || cancellation != null) {
-			// stop HgChangelog.Iterator. Our exception is for the purposes of cancellation only,
-			// the one we have stored (this.cancellation) is for user
-			throw new CancelledException(); 
+	public <T> T getAdapter(Class<T> adapterClass) {
+		if (adapterClass == Lifecycle.class) {
+			return adapterClass.cast(lifecycleBridge);
 		}
-	}
-
-	public <T> T getAdapter(Class<T> adapterClass) {
-		if (adapterClass == ProgressSupport.class) {
-			return adapterClass.cast(progressHelper);
-		}
-		return null;
+		// just in case there are more adapters in future
+		return Adaptable.Factory.getAdapter(handler, adapterClass, null);
 	}
 }
\ No newline at end of file