comparison src/org/tmatesoft/hg/core/HgDiffCommand.java @ 632:54e16ab771ec v1.1rc2

Progress/cancel for HgDiffCommand. Renamed execute method
author Artem Tikhomirov <tikhomirov.artem@gmail.com>
date Thu, 30 May 2013 16:13:43 +0200
parents 72c979555cb8
children a20121a2bba6
comparison
equal deleted inserted replaced
631:8a5cdcb27b8f 632:54e16ab771ec
19 import static org.tmatesoft.hg.repo.HgRepository.NO_REVISION; 19 import static org.tmatesoft.hg.repo.HgRepository.NO_REVISION;
20 import static org.tmatesoft.hg.repo.HgRepository.TIP; 20 import static org.tmatesoft.hg.repo.HgRepository.TIP;
21 21
22 import org.tmatesoft.hg.internal.BlameHelper; 22 import org.tmatesoft.hg.internal.BlameHelper;
23 import org.tmatesoft.hg.internal.CsetParamKeeper; 23 import org.tmatesoft.hg.internal.CsetParamKeeper;
24 import org.tmatesoft.hg.internal.Experimental;
25 import org.tmatesoft.hg.internal.FileHistory; 24 import org.tmatesoft.hg.internal.FileHistory;
26 import org.tmatesoft.hg.internal.FileRevisionHistoryChunk; 25 import org.tmatesoft.hg.internal.FileRevisionHistoryChunk;
27 import org.tmatesoft.hg.repo.HgDataFile; 26 import org.tmatesoft.hg.repo.HgDataFile;
28 import org.tmatesoft.hg.repo.HgRepository; 27 import org.tmatesoft.hg.repo.HgRepository;
29 import org.tmatesoft.hg.repo.HgRuntimeException; 28 import org.tmatesoft.hg.repo.HgRuntimeException;
29 import org.tmatesoft.hg.util.CancelSupport;
30 import org.tmatesoft.hg.util.CancelledException; 30 import org.tmatesoft.hg.util.CancelledException;
31 import org.tmatesoft.hg.util.Path; 31 import org.tmatesoft.hg.util.Path;
32 import org.tmatesoft.hg.util.ProgressSupport;
32 33
33 /** 34 /**
34 * 'hg diff' counterpart, with similar, diff-based, functionality 35 * 'hg diff' counterpart, with similar, although not identical, functionality.
36 * Despite both 'hg diff' and this command are diff-based, implementation
37 * peculiarities may lead to slightly different diff results. Either is valid
38 * as there's no strict diff specification.
39 *
40 * <p>
41 * <strong>Note</strong>, at the moment this command annotates single file only. Diff over
42 * complete repository (all the file changed in a given changeset) might
43 * be added later.
35 * 44 *
36 * @since 1.1 45 * @since 1.1
37 * @author Artem Tikhomirov 46 * @author Artem Tikhomirov
38 * @author TMate Software Ltd. 47 * @author TMate Software Ltd.
39 */ 48 */
40 @Experimental(reason="#execute* methods might get renamed")
41 public class HgDiffCommand extends HgAbstractCommand<HgDiffCommand> { 49 public class HgDiffCommand extends HgAbstractCommand<HgDiffCommand> {
42 50
43 private final HgRepository repo; 51 private final HgRepository repo;
44 private HgDataFile df; 52 private HgDataFile df;
45 private final CsetParamKeeper clogRevIndexStart, clogRevIndexEnd; 53 private final CsetParamKeeper clogRevIndexStart, clogRevIndexEnd;
84 clogRevIndexEnd.set(changelogRevIndexEnd); 92 clogRevIndexEnd.set(changelogRevIndexEnd);
85 return this; 93 return this;
86 } 94 }
87 95
88 /** 96 /**
89 * Selects revision for {@link #executeAnnotateSingleRevision(HgBlameInspector)}, the one 97 * Selects revision for {@link #executeParentsAnnotate(HgBlameInspector)}, the one
90 * to diff against its parents. 98 * to diff against its parents.
91 * 99 *
92 * Besides, it is handy when range of interest spans up to the very beginning of the file history 100 * Besides, it is handy when range of interest spans up to the very beginning of the file history
93 * (and thus is equivalent to <code>range(0, changelogRevIndex)</code>) 101 * (and thus is equivalent to <code>range(0, changelogRevIndex)</code>)
94 * 102 *
105 /** 113 /**
106 * Revision differences are reported in selected order when 114 * Revision differences are reported in selected order when
107 * annotating {@link #range(int, int) range} of changesets with 115 * annotating {@link #range(int, int) range} of changesets with
108 * {@link #executeAnnotate(HgBlameInspector)}. 116 * {@link #executeAnnotate(HgBlameInspector)}.
109 * <p> 117 * <p>
110 * This method doesn't affect {@link #executeAnnotateSingleRevision(HgBlameInspector)} and 118 * This method doesn't affect {@link #executeParentsAnnotate(HgBlameInspector)} and
111 * {@link #executeDiff(HgBlameInspector)} 119 * {@link #executeDiff(HgBlameInspector)}
112 * 120 *
113 * @param order desired iteration order 121 * @param order desired iteration order
114 * @return <code>this</code> for convenience 122 * @return <code>this</code> for convenience
115 */ 123 */
116 public HgDiffCommand order(HgIterateDirection order) { 124 public HgDiffCommand order(HgIterateDirection order) {
117 iterateDirection = order; 125 iterateDirection = order;
118 return this; 126 return this;
119 } 127 }
120
121 // FIXME progress and cancellation
122 128
123 /** 129 /**
124 * Diff two revisions selected with {@link #range(int, int)} against each other. 130 * Diff two revisions selected with {@link #range(int, int)} against each other.
125 * <p>mimics 'hg diff -r clogRevIndex1 -r clogRevIndex2' 131 * <p>mimics 'hg diff -r clogRevIndex1 -r clogRevIndex2'
126 * 132 *
128 * @throws CancelledException if execution of the command was cancelled 134 * @throws CancelledException if execution of the command was cancelled
129 * @throws HgException subclass thereof to indicate specific issue with the command arguments or repository state 135 * @throws HgException subclass thereof to indicate specific issue with the command arguments or repository state
130 */ 136 */
131 public void executeDiff(HgBlameInspector insp) throws HgCallbackTargetException, CancelledException, HgException { 137 public void executeDiff(HgBlameInspector insp) throws HgCallbackTargetException, CancelledException, HgException {
132 checkFile(); 138 checkFile();
139 final ProgressSupport progress = getProgressSupport(insp);
140 progress.start(2);
133 try { 141 try {
142 final CancelSupport cancel = getCancelSupport(insp, true);
134 int fileRevIndex1 = fileRevIndex(df, clogRevIndexStart.get()); 143 int fileRevIndex1 = fileRevIndex(df, clogRevIndexStart.get());
135 int fileRevIndex2 = fileRevIndex(df, clogRevIndexEnd.get()); 144 int fileRevIndex2 = fileRevIndex(df, clogRevIndexEnd.get());
136 BlameHelper bh = new BlameHelper(insp); 145 BlameHelper bh = new BlameHelper(insp);
137 bh.prepare(df, clogRevIndexStart.get(), clogRevIndexEnd.get()); 146 bh.prepare(df, clogRevIndexStart.get(), clogRevIndexEnd.get());
147 progress.worked(1);
148 cancel.checkCancelled();
138 bh.diff(fileRevIndex1, clogRevIndexStart.get(), fileRevIndex2, clogRevIndexEnd.get()); 149 bh.diff(fileRevIndex1, clogRevIndexStart.get(), fileRevIndex2, clogRevIndexEnd.get());
150 progress.worked(1);
151 cancel.checkCancelled();
139 } catch (HgRuntimeException ex) { 152 } catch (HgRuntimeException ex) {
140 throw new HgLibraryFailureException(ex); 153 throw new HgLibraryFailureException(ex);
154 } finally {
155 progress.done();
141 } 156 }
142 } 157 }
143 158
144 /** 159 /**
145 * Walk file history {@link #range(int, int) range} and report changes (diff) for each revision 160 * Walk file history {@link #range(int, int) range} and report changes (diff) for each revision
148 * @throws CancelledException if execution of the command was cancelled 163 * @throws CancelledException if execution of the command was cancelled
149 * @throws HgException subclass thereof to indicate specific issue with the command arguments or repository state 164 * @throws HgException subclass thereof to indicate specific issue with the command arguments or repository state
150 */ 165 */
151 public void executeAnnotate(HgBlameInspector insp) throws HgCallbackTargetException, CancelledException, HgException { 166 public void executeAnnotate(HgBlameInspector insp) throws HgCallbackTargetException, CancelledException, HgException {
152 checkFile(); 167 checkFile();
168 ProgressSupport progress = null;
153 try { 169 try {
154 if (!df.exists()) { 170 if (!df.exists()) {
155 return; 171 return;
156 } 172 }
173 final CancelSupport cancel = getCancelSupport(insp, true);
157 BlameHelper bh = new BlameHelper(insp); 174 BlameHelper bh = new BlameHelper(insp);
158 FileHistory fileHistory = bh.prepare(df, clogRevIndexStart.get(), clogRevIndexEnd.get()); 175 FileHistory fileHistory = bh.prepare(df, clogRevIndexStart.get(), clogRevIndexEnd.get());
159 176 //
177 cancel.checkCancelled();
178 int totalWork = 0;
179 for (FileRevisionHistoryChunk fhc : fileHistory.iterate(iterateDirection)) {
180 totalWork += fhc.revisionCount();
181 }
182 progress = getProgressSupport(insp);
183 progress.start(totalWork + 1);
184 progress.worked(1); // BlameHelper.prepare
185 //
160 int[] fileClogParentRevs = new int[2]; 186 int[] fileClogParentRevs = new int[2];
161 int[] fileParentRevs = new int[2]; 187 int[] fileParentRevs = new int[2];
162 for (FileRevisionHistoryChunk fhc : fileHistory.iterate(iterateDirection)) { 188 for (FileRevisionHistoryChunk fhc : fileHistory.iterate(iterateDirection)) {
163 for (int fri : fhc.fileRevisions(iterateDirection)) { 189 for (int fri : fhc.fileRevisions(iterateDirection)) {
164 int clogRevIndex = fhc.changeset(fri); 190 int clogRevIndex = fhc.changeset(fri);
166 assert clogRevIndex >= clogRevIndexStart.get(); 192 assert clogRevIndex >= clogRevIndexStart.get();
167 assert clogRevIndex <= clogRevIndexEnd.get(); 193 assert clogRevIndex <= clogRevIndexEnd.get();
168 fhc.fillFileParents(fri, fileParentRevs); 194 fhc.fillFileParents(fri, fileParentRevs);
169 fhc.fillCsetParents(fri, fileClogParentRevs); 195 fhc.fillCsetParents(fri, fileClogParentRevs);
170 bh.annotateChange(fri, clogRevIndex, fileParentRevs, fileClogParentRevs); 196 bh.annotateChange(fri, clogRevIndex, fileParentRevs, fileClogParentRevs);
197 progress.worked(1);
198 cancel.checkCancelled();
171 } 199 }
172 } 200 }
173 } catch (HgRuntimeException ex) { 201 } catch (HgRuntimeException ex) {
174 throw new HgLibraryFailureException(ex); 202 throw new HgLibraryFailureException(ex);
203 } finally {
204 if (progress != null) {
205 progress.done();
206 }
175 } 207 }
176 } 208 }
177 209
178 /** 210 /**
179 * Annotates changes of the file against its parent(s). 211 * Annotates changes of the file against its parent(s).
182 * 214 *
183 * @throws HgCallbackTargetException propagated exception from the handler 215 * @throws HgCallbackTargetException propagated exception from the handler
184 * @throws CancelledException if execution of the command was cancelled 216 * @throws CancelledException if execution of the command was cancelled
185 * @throws HgException subclass thereof to indicate specific issue with the command arguments or repository state 217 * @throws HgException subclass thereof to indicate specific issue with the command arguments or repository state
186 */ 218 */
187 public void executeAnnotateSingleRevision(HgBlameInspector insp) throws HgCallbackTargetException, CancelledException, HgException { 219 public void executeParentsAnnotate(HgBlameInspector insp) throws HgCallbackTargetException, CancelledException, HgException {
188 checkFile(); 220 checkFile();
221 final ProgressSupport progress = getProgressSupport(insp);
222 progress.start(2);
189 try { 223 try {
224 final CancelSupport cancel = getCancelSupport(insp, true);
190 int changelogRevisionIndex = clogRevIndexEnd.get(); 225 int changelogRevisionIndex = clogRevIndexEnd.get();
191 // TODO detect if file is text/binary (e.g. looking for chars < ' ' and not \t\r\n\f 226 // TODO detect if file is text/binary (e.g. looking for chars < ' ' and not \t\r\n\f
192 int fileRevIndex = fileRevIndex(df, changelogRevisionIndex); 227 int fileRevIndex = fileRevIndex(df, changelogRevisionIndex);
193 int[] fileRevParents = new int[2]; 228 int[] fileRevParents = new int[2];
194 df.parents(fileRevIndex, fileRevParents, null, null); 229 df.parents(fileRevIndex, fileRevParents, null, null);
199 fileClogParentRevs[0] = fileRevParents[0] == NO_REVISION ? NO_REVISION : df.getChangesetRevisionIndex(fileRevParents[0]); 234 fileClogParentRevs[0] = fileRevParents[0] == NO_REVISION ? NO_REVISION : df.getChangesetRevisionIndex(fileRevParents[0]);
200 fileClogParentRevs[1] = fileRevParents[1] == NO_REVISION ? NO_REVISION : df.getChangesetRevisionIndex(fileRevParents[1]); 235 fileClogParentRevs[1] = fileRevParents[1] == NO_REVISION ? NO_REVISION : df.getChangesetRevisionIndex(fileRevParents[1]);
201 BlameHelper bh = new BlameHelper(insp); 236 BlameHelper bh = new BlameHelper(insp);
202 int clogIndexStart = fileClogParentRevs[0] == NO_REVISION ? (fileClogParentRevs[1] == NO_REVISION ? 0 : fileClogParentRevs[1]) : fileClogParentRevs[0]; 237 int clogIndexStart = fileClogParentRevs[0] == NO_REVISION ? (fileClogParentRevs[1] == NO_REVISION ? 0 : fileClogParentRevs[1]) : fileClogParentRevs[0];
203 bh.prepare(df, clogIndexStart, changelogRevisionIndex); 238 bh.prepare(df, clogIndexStart, changelogRevisionIndex);
239 progress.worked(1);
240 cancel.checkCancelled();
204 bh.annotateChange(fileRevIndex, changelogRevisionIndex, fileRevParents, fileClogParentRevs); 241 bh.annotateChange(fileRevIndex, changelogRevisionIndex, fileRevParents, fileClogParentRevs);
242 progress.worked(1);
243 cancel.checkCancelled();
205 } catch (HgRuntimeException ex) { 244 } catch (HgRuntimeException ex) {
206 throw new HgLibraryFailureException(ex); 245 throw new HgLibraryFailureException(ex);
246 } finally {
247 progress.done();
207 } 248 }
208 } 249 }
209 250
210 private void checkFile() { 251 private void checkFile() {
211 if (df == null) { 252 if (df == null) {