Mercurial > jhg
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) { |
