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