Mercurial > hg4j
comparison src/org/tmatesoft/hg/core/HgLogCommand.java @ 215:41a778e3fd31
Issue 5: Facilities for progress and cancellation. More specific exceptions. Exceptions from callbacks as RuntimeException
| author | Artem Tikhomirov <tikhomirov.artem@gmail.com> |
|---|---|
| date | Tue, 17 May 2011 00:56:54 +0200 |
| parents | ffc5f6d59f7e |
| children | 1792b37650f2 |
comparison
equal
deleted
inserted
replaced
| 214:4252faa556cd | 215:41a778e3fd31 |
|---|---|
| 25 import java.util.LinkedList; | 25 import java.util.LinkedList; |
| 26 import java.util.List; | 26 import java.util.List; |
| 27 import java.util.Set; | 27 import java.util.Set; |
| 28 import java.util.TreeSet; | 28 import java.util.TreeSet; |
| 29 | 29 |
| 30 import org.tmatesoft.hg.repo.HgChangelog; | |
| 30 import org.tmatesoft.hg.repo.HgChangelog.RawChangeset; | 31 import org.tmatesoft.hg.repo.HgChangelog.RawChangeset; |
| 31 import org.tmatesoft.hg.repo.HgChangelog; | |
| 32 import org.tmatesoft.hg.repo.HgDataFile; | 32 import org.tmatesoft.hg.repo.HgDataFile; |
| 33 import org.tmatesoft.hg.repo.HgRepository; | 33 import org.tmatesoft.hg.repo.HgRepository; |
| 34 import org.tmatesoft.hg.util.ByteChannel; | 34 import org.tmatesoft.hg.util.ByteChannel; |
| 35 import org.tmatesoft.hg.util.CancelledException; | 35 import org.tmatesoft.hg.util.CancelledException; |
| 36 import org.tmatesoft.hg.util.Path; | 36 import org.tmatesoft.hg.util.Path; |
| 37 import org.tmatesoft.hg.util.ProgressSupport; | |
| 37 | 38 |
| 38 | 39 |
| 39 /** | 40 /** |
| 40 * Access to changelog, 'hg log' command counterpart. | 41 * Access to changelog, 'hg log' command counterpart. |
| 41 * | 42 * |
| 46 * Not thread-safe (each thread has to use own {@link HgLogCommand} instance). | 47 * Not thread-safe (each thread has to use own {@link HgLogCommand} instance). |
| 47 * | 48 * |
| 48 * @author Artem Tikhomirov | 49 * @author Artem Tikhomirov |
| 49 * @author TMate Software Ltd. | 50 * @author TMate Software Ltd. |
| 50 */ | 51 */ |
| 51 public class HgLogCommand implements HgChangelog.Inspector { | 52 public class HgLogCommand extends HgAbstractCommand<HgLogCommand> implements HgChangelog.Inspector { |
| 52 | 53 |
| 53 private final HgRepository repo; | 54 private final HgRepository repo; |
| 54 private Set<String> users; | 55 private Set<String> users; |
| 55 private Set<String> branches; | 56 private Set<String> branches; |
| 56 private int limit = 0, count = 0; | 57 private int limit = 0, count = 0; |
| 162 } | 163 } |
| 163 | 164 |
| 164 /** | 165 /** |
| 165 * Similar to {@link #execute(org.tmatesoft.hg.repo.RawChangeset.Inspector)}, collects and return result as a list. | 166 * Similar to {@link #execute(org.tmatesoft.hg.repo.RawChangeset.Inspector)}, collects and return result as a list. |
| 166 */ | 167 */ |
| 167 public List<HgChangeset> execute() throws HgException { | 168 public List<HgChangeset> execute() throws HgDataStreamException { |
| 168 CollectHandler collector = new CollectHandler(); | 169 CollectHandler collector = new CollectHandler(); |
| 169 execute(collector); | 170 try { |
| 171 execute(collector); | |
| 172 } catch (HgCallbackTargetException ex) { | |
| 173 // can't happen as long as our CollectHandler doesn't throw any exception | |
| 174 throw new HgBadStateException(ex.getCause()); | |
| 175 } catch (CancelledException ex) { | |
| 176 // can't happen, see above | |
| 177 throw new HgBadStateException(ex); | |
| 178 } | |
| 170 return collector.getChanges(); | 179 return collector.getChanges(); |
| 171 } | 180 } |
| 172 | 181 |
| 173 /** | 182 /** |
| 174 * | 183 * |
| 175 * @param handler callback to process changesets. | 184 * @param handler callback to process changesets. |
| 176 * @throws IllegalArgumentException when inspector argument is null | 185 * @throws IllegalArgumentException when inspector argument is null |
| 177 * @throws ConcurrentModificationException if this log command instance is already running | 186 * @throws ConcurrentModificationException if this log command instance is already running |
| 178 */ | 187 */ |
| 179 public void execute(HgChangesetHandler handler) throws HgException { | 188 public void execute(HgChangesetHandler handler) throws HgDataStreamException, HgCallbackTargetException, CancelledException { |
| 180 if (handler == null) { | 189 if (handler == null) { |
| 181 throw new IllegalArgumentException(); | 190 throw new IllegalArgumentException(); |
| 182 } | 191 } |
| 183 if (csetTransform != null) { | 192 if (csetTransform != null) { |
| 184 throw new ConcurrentModificationException(); | 193 throw new ConcurrentModificationException(); |
| 185 } | 194 } |
| 195 final ProgressSupport progressHelper = getProgressSupport(handler); | |
| 186 try { | 196 try { |
| 187 count = 0; | 197 count = 0; |
| 188 HgChangelog.ParentWalker pw = parentHelper; // leave it uninitialized unless we iterate whole repo | 198 HgChangelog.ParentWalker pw = parentHelper; // leave it uninitialized unless we iterate whole repo |
| 189 if (file == null) { | 199 if (file == null) { |
| 190 pw = getParentHelper(); | 200 pw = getParentHelper(); |
| 191 } | 201 } |
| 192 // ChangesetTransfrom creates a blank PathPool, and #file(String, boolean) above | 202 // ChangesetTransfrom creates a blank PathPool, and #file(String, boolean) above |
| 193 // may utilize it as well. CommandContext? How about StatusCollector there as well? | 203 // may utilize it as well. CommandContext? How about StatusCollector there as well? |
| 194 csetTransform = new ChangesetTransformer(repo, handler, pw); | 204 csetTransform = new ChangesetTransformer(repo, handler, pw, progressHelper, getCancelSupport(handler)); |
| 195 if (file == null) { | 205 if (file == null) { |
| 206 progressHelper.start(endRev - startRev + 1); | |
| 196 repo.getChangelog().range(startRev, endRev, this); | 207 repo.getChangelog().range(startRev, endRev, this); |
| 208 csetTransform.checkFailure(); | |
| 197 } else { | 209 } else { |
| 210 progressHelper.start(-1/*XXX enum const, or a dedicated method startUnspecified(). How about startAtLeast(int)?*/); | |
| 198 HgDataFile fileNode = repo.getFileNode(file); | 211 HgDataFile fileNode = repo.getFileNode(file); |
| 199 fileNode.history(startRev, endRev, this); | 212 fileNode.history(startRev, endRev, this); |
| 213 csetTransform.checkFailure(); | |
| 200 if (fileNode.isCopy()) { | 214 if (fileNode.isCopy()) { |
| 201 // even if we do not follow history, report file rename | 215 // even if we do not follow history, report file rename |
| 202 do { | 216 do { |
| 203 if (handler instanceof FileHistoryHandler) { | 217 if (handler instanceof FileHistoryHandler) { |
| 204 FileRevision src = new FileRevision(repo, fileNode.getCopySourceRevision(), fileNode.getCopySourceName()); | 218 FileRevision src = new FileRevision(repo, fileNode.getCopySourceRevision(), fileNode.getCopySourceName()); |
| 205 FileRevision dst = new FileRevision(repo, fileNode.getRevision(0), fileNode.getPath()); | 219 FileRevision dst = new FileRevision(repo, fileNode.getRevision(0), fileNode.getPath()); |
| 206 ((FileHistoryHandler) handler).copy(src, dst); | 220 try { |
| 221 ((FileHistoryHandler) handler).copy(src, dst); | |
| 222 } catch (RuntimeException ex) { | |
| 223 throw new HgCallbackTargetException(ex).setRevision(fileNode.getCopySourceRevision()).setFileName(fileNode.getCopySourceName()); | |
| 224 } | |
| 207 } | 225 } |
| 208 if (limit > 0 && count >= limit) { | 226 if (limit > 0 && count >= limit) { |
| 209 // if limit reach, follow is useless. | 227 // if limit reach, follow is useless. |
| 210 break; | 228 break; |
| 211 } | 229 } |
| 212 if (followHistory) { | 230 if (followHistory) { |
| 213 fileNode = repo.getFileNode(fileNode.getCopySourceName()); | 231 fileNode = repo.getFileNode(fileNode.getCopySourceName()); |
| 214 fileNode.history(this); | 232 fileNode.history(this); |
| 233 csetTransform.checkFailure(); | |
| 215 } | 234 } |
| 216 } while (followHistory && fileNode.isCopy()); | 235 } while (followHistory && fileNode.isCopy()); |
| 217 } | 236 } |
| 218 } | 237 } |
| 219 } finally { | 238 } finally { |
| 220 csetTransform = null; | 239 csetTransform = null; |
| 240 progressHelper.done(); | |
| 221 } | 241 } |
| 222 } | 242 } |
| 223 | 243 |
| 224 // | 244 // |
| 225 | 245 |
