Mercurial > jhg
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 } |