comparison 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
comparison
equal deleted inserted replaced
519:934037edbea0 520:1ee452f31187
16 */ 16 */
17 package org.tmatesoft.hg.core; 17 package org.tmatesoft.hg.core;
18 18
19 import java.util.Set; 19 import java.util.Set;
20 20
21 import org.tmatesoft.hg.internal.Lifecycle;
22 import org.tmatesoft.hg.internal.LifecycleBridge;
21 import org.tmatesoft.hg.internal.PathPool; 23 import org.tmatesoft.hg.internal.PathPool;
22 import org.tmatesoft.hg.repo.HgChangelog; 24 import org.tmatesoft.hg.repo.HgChangelog;
23 import org.tmatesoft.hg.repo.HgChangelog.RawChangeset; 25 import org.tmatesoft.hg.repo.HgChangelog.RawChangeset;
24 import org.tmatesoft.hg.repo.HgRepository; 26 import org.tmatesoft.hg.repo.HgRepository;
25 import org.tmatesoft.hg.repo.HgStatusCollector; 27 import org.tmatesoft.hg.repo.HgStatusCollector;
35 * TODO post-1.0 Move to .internal once access to package-local HgChangeset cons is resolved. For 1.0, enough it's package-local 37 * TODO post-1.0 Move to .internal once access to package-local HgChangeset cons is resolved. For 1.0, enough it's package-local
36 * 38 *
37 * @author Artem Tikhomirov 39 * @author Artem Tikhomirov
38 * @author TMate Software Ltd. 40 * @author TMate Software Ltd.
39 */ 41 */
40 /*package-local*/ class ChangesetTransformer implements HgChangelog.Inspector, Adaptable, CancelSupport { 42 /*package-local*/ class ChangesetTransformer implements HgChangelog.Inspector, Adaptable {
41 private final HgChangesetHandler handler; 43 private final HgChangesetHandler handler;
42 private final ProgressSupport progressHelper; 44 private final LifecycleBridge lifecycleBridge;
43 private final CancelSupport cancelHelper;
44 private final Transformation t; 45 private final Transformation t;
45 private Set<String> branches; 46 private Set<String> branches;
46 private HgCallbackTargetException failure; 47 private HgCallbackTargetException failure;
47 private CancelledException cancellation;
48 48
49 // repo and delegate can't be null, parent walker can 49 // repo and delegate can't be null, parent walker can
50 // ps and cs can't be null 50 // ps and cs can't be null
51 public ChangesetTransformer(HgRepository hgRepo, HgChangesetHandler delegate, HgParentChildMap<HgChangelog> pw, ProgressSupport ps, CancelSupport cs) { 51 public ChangesetTransformer(HgRepository hgRepo, HgChangesetHandler delegate, HgParentChildMap<HgChangelog> pw, ProgressSupport ps, CancelSupport cs) {
52 if (hgRepo == null || delegate == null) { 52 if (hgRepo == null || delegate == null) {
56 throw new IllegalArgumentException(); 56 throw new IllegalArgumentException();
57 } 57 }
58 HgStatusCollector statusCollector = new HgStatusCollector(hgRepo); 58 HgStatusCollector statusCollector = new HgStatusCollector(hgRepo);
59 t = new Transformation(statusCollector, pw); 59 t = new Transformation(statusCollector, pw);
60 handler = delegate; 60 handler = delegate;
61 // we let HgChangelog#range deal with progress (pipe through getAdapter) 61 // lifecycleBridge takes care of progress and cancellation, plus
62 // but use own cancellation (which involves CallbackTargetException as well, and preserves original cancellation 62 // gives us explicit way to stop iteration (once HgCallbackTargetException) comes.
63 // exception in case clients care) 63 lifecycleBridge = new LifecycleBridge(ps, cs);
64 cancelHelper = cs;
65 progressHelper = ps;
66 } 64 }
67 65
68 public void next(int revisionNumber, Nodeid nodeid, RawChangeset cset) { 66 public void next(int revisionNumber, Nodeid nodeid, RawChangeset cset) {
69 if (branches != null && !branches.contains(cset.branch())) { 67 if (branches != null && !branches.contains(cset.branch())) {
70 return; 68 return;
71 } 69 }
72 70
73 HgChangeset changeset = t.handle(revisionNumber, nodeid, cset); 71 HgChangeset changeset = t.handle(revisionNumber, nodeid, cset);
74 try { 72 try {
75 handler.cset(changeset); 73 handler.cset(changeset);
76 cancelHelper.checkCancelled(); 74 lifecycleBridge.nextStep();
77 } catch (HgCallbackTargetException ex) { 75 } catch (HgCallbackTargetException ex) {
78 failure = ex.setRevision(nodeid).setRevisionIndex(revisionNumber); 76 failure = ex.setRevision(nodeid).setRevisionIndex(revisionNumber);
79 } catch (CancelledException ex) { 77 lifecycleBridge.stop();
80 cancellation = ex;
81 } 78 }
82 } 79 }
83 80
84 public void checkFailure() throws HgCallbackTargetException, CancelledException { 81 public void checkFailure() throws HgCallbackTargetException, CancelledException {
85 if (failure != null) { 82 if (failure != null) {
86 HgCallbackTargetException toThrow = failure; 83 HgCallbackTargetException toThrow = failure;
87 failure = null; // just in (otherwise unexpected) case this instance would get reused
88 throw toThrow; 84 throw toThrow;
89 } 85 }
90 if (cancellation != null) { 86 if (lifecycleBridge.isCancelled()) {
91 CancelledException toThrow = cancellation; 87 CancelledException toThrow = lifecycleBridge.getCancelOrigin();
92 cancellation = null; 88 assert toThrow != null;
93 throw toThrow; 89 throw toThrow;
94 } 90 }
95 } 91 }
96 92
97 public void limitBranches(Set<String> branches) { 93 public void limitBranches(Set<String> branches) {
119 changeset.init(revisionNumber, nodeid, cset); 115 changeset.init(revisionNumber, nodeid, cset);
120 return changeset; 116 return changeset;
121 } 117 }
122 } 118 }
123 119
124 public void checkCancelled() throws CancelledException { 120 public <T> T getAdapter(Class<T> adapterClass) {
125 if (failure != null || cancellation != null) { 121 if (adapterClass == Lifecycle.class) {
126 // stop HgChangelog.Iterator. Our exception is for the purposes of cancellation only, 122 return adapterClass.cast(lifecycleBridge);
127 // the one we have stored (this.cancellation) is for user
128 throw new CancelledException();
129 } 123 }
130 } 124 // just in case there are more adapters in future
131 125 return Adaptable.Factory.getAdapter(handler, adapterClass, null);
132 public <T> T getAdapter(Class<T> adapterClass) {
133 if (adapterClass == ProgressSupport.class) {
134 return adapterClass.cast(progressHelper);
135 }
136 return null;
137 } 126 }
138 } 127 }