comparison src/org/tmatesoft/hg/repo/HgStatusCollector.java @ 423:9c9c442b5f2e

Major refactoring of exception handling. Low-level API uses RuntimeExceptions, while checked are left for higher level
author Artem Tikhomirov <tikhomirov.artem@gmail.com>
date Fri, 23 Mar 2012 22:51:18 +0100
parents 866fc3b597a0
children 6437d261048a
comparison
equal deleted inserted replaced
422:5d1cc7366d04 423:9c9c442b5f2e
24 import java.util.LinkedList; 24 import java.util.LinkedList;
25 import java.util.List; 25 import java.util.List;
26 import java.util.Map; 26 import java.util.Map;
27 import java.util.TreeSet; 27 import java.util.TreeSet;
28 28
29 import org.tmatesoft.hg.core.HgBadStateException;
30 import org.tmatesoft.hg.core.HgException; 29 import org.tmatesoft.hg.core.HgException;
31 import org.tmatesoft.hg.core.HgInvalidControlFileException;
32 import org.tmatesoft.hg.core.HgInvalidRevisionException;
33 import org.tmatesoft.hg.core.Nodeid; 30 import org.tmatesoft.hg.core.Nodeid;
34 import org.tmatesoft.hg.internal.IntMap; 31 import org.tmatesoft.hg.internal.IntMap;
35 import org.tmatesoft.hg.internal.ManifestRevision; 32 import org.tmatesoft.hg.internal.ManifestRevision;
36 import org.tmatesoft.hg.internal.Pool; 33 import org.tmatesoft.hg.internal.Pool;
34 import org.tmatesoft.hg.util.CancelSupport;
35 import org.tmatesoft.hg.util.CancelledException;
37 import org.tmatesoft.hg.util.Path; 36 import org.tmatesoft.hg.util.Path;
38 import org.tmatesoft.hg.util.PathPool; 37 import org.tmatesoft.hg.util.PathPool;
39 import org.tmatesoft.hg.util.PathRewrite; 38 import org.tmatesoft.hg.util.PathRewrite;
40 39
41 40
42 /** 41 /**
43 * RevisionWalker? 42 * Collect status information for changes between two repository revisions.
44 * 43 *
45 * @author Artem Tikhomirov 44 * @author Artem Tikhomirov
46 * @author TMate Software Ltd. 45 * @author TMate Software Ltd.
47 */ 46 */
48 public class HgStatusCollector { 47 public class HgStatusCollector {
128 } 127 }
129 return true; 128 return true;
130 } 129 }
131 130
132 public boolean next(Nodeid nid, String fname, String flags) { 131 public boolean next(Nodeid nid, String fname, String flags) {
133 throw new HgBadStateException(HgManifest.Inspector2.class.getName()); 132 throw new IllegalStateException(HgManifest.Inspector2.class.getName());
134 } 133 }
135 134
136 public boolean next(Nodeid nid, Path fname, HgManifest.Flags flags) { 135 public boolean next(Nodeid nid, Path fname, HgManifest.Flags flags) {
137 if (!cacheHit) { 136 if (!cacheHit) {
138 delegate.next(nid, fname, flags); 137 delegate.next(nid, fname, flags);
191 } 190 }
192 191
193 /** 192 /**
194 * 'hg status --change REV' command counterpart. 193 * 'hg status --change REV' command counterpart.
195 * 194 *
196 * @throws HgInvalidRevisionException if argument specifies non-existent revision index 195 * @throws CancelledException if operation execution was cancelled
197 * @throws HgInvalidControlFileException if access to revlog index/data entry failed 196 * @throws HgRuntimeException subclass thereof to indicate issues with the library. <em>Runtime exception</em>
198 */ 197 */
199 public void change(int revisionIndex, HgStatusInspector inspector) throws HgInvalidRevisionException, HgInvalidControlFileException { 198 public void change(int revisionIndex, HgStatusInspector inspector) throws CancelledException, HgRuntimeException {
200 int p; 199 int p;
201 if (revisionIndex == 0) { 200 if (revisionIndex == 0) {
202 p = NO_REVISION; 201 p = NO_REVISION;
203 } else { 202 } else {
204 int[] parents = new int[2]; 203 int[] parents = new int[2];
211 210
212 /** 211 /**
213 * Parameters <b>rev1</b> and <b>rev2</b> are changelog revision indexes, shall not be the same. Argument order matters. 212 * Parameters <b>rev1</b> and <b>rev2</b> are changelog revision indexes, shall not be the same. Argument order matters.
214 * Either rev1 or rev2 may be {@link HgRepository#NO_REVISION} to indicate comparison to empty repository 213 * Either rev1 or rev2 may be {@link HgRepository#NO_REVISION} to indicate comparison to empty repository
215 * 214 *
216 * FIXME cancellation (at least exception)?
217 *
218 * @param rev1 <em>from</em> changeset index, non-negative or {@link HgRepository#TIP} 215 * @param rev1 <em>from</em> changeset index, non-negative or {@link HgRepository#TIP}
219 * @param rev2 <em>to</em> changeset index, non-negative or {@link HgRepository#TIP} 216 * @param rev2 <em>to</em> changeset index, non-negative or {@link HgRepository#TIP}
220 * @param inspector callback for status information 217 * @param inspector callback for status information
221 * @throws HgInvalidRevisionException if any argument specifies non-existent revision index 218 * @throws CancelledException if operation execution was cancelled
219 * @throws HgRuntimeException subclass thereof to indicate issues with the library. <em>Runtime exception</em>
222 * @throws IllegalArgumentException inspector other incorrect argument values 220 * @throws IllegalArgumentException inspector other incorrect argument values
223 * @throws HgInvalidControlFileException if access to revlog index/data entry failed 221 */
224 */ 222 public void walk(int rev1, int rev2, HgStatusInspector inspector) throws CancelledException, HgRuntimeException, IllegalArgumentException {
225 public void walk(int rev1, int rev2, HgStatusInspector inspector) throws HgInvalidRevisionException, HgInvalidControlFileException {
226 if (rev1 == rev2) { 223 if (rev1 == rev2) {
227 throw new IllegalArgumentException(); 224 throw new IllegalArgumentException();
228 } 225 }
229 if (inspector == null) { 226 if (inspector == null) {
230 throw new IllegalArgumentException(); 227 throw new IllegalArgumentException();
276 } 273 }
277 } 274 }
278 r1 = get(rev1); 275 r1 = get(rev1);
279 r2 = get(rev2); 276 r2 = get(rev2);
280 277
278 final CancelSupport cs = CancelSupport.Factory.get(inspector);
279
281 TreeSet<Path> r1Files = new TreeSet<Path>(r1.files()); 280 TreeSet<Path> r1Files = new TreeSet<Path>(r1.files());
282 for (Path r2fname : r2.files()) { 281 for (Path r2fname : r2.files()) {
283 if (!scope.accept(r2fname)) { 282 if (!scope.accept(r2fname)) {
284 continue; 283 continue;
285 } 284 }
291 if (nidR1.equals(nidR2) && flagsR2 == flagsR1) { 290 if (nidR1.equals(nidR2) && flagsR2 == flagsR1) {
292 inspector.clean(r2fname); 291 inspector.clean(r2fname);
293 } else { 292 } else {
294 inspector.modified(r2fname); 293 inspector.modified(r2fname);
295 } 294 }
295 cs.checkCancelled();
296 } else { 296 } else {
297 try { 297 try {
298 Path copyTarget = r2fname; 298 Path copyTarget = r2fname;
299 Path copyOrigin = getOriginIfCopy(repo, copyTarget, r1Files, rev1); 299 Path copyOrigin = getOriginIfCopy(repo, copyTarget, r1Files, rev1);
300 if (copyOrigin != null) { 300 if (copyOrigin != null) {
305 } catch (HgException ex) { 305 } catch (HgException ex) {
306 // record exception to a mediator and continue, 306 // record exception to a mediator and continue,
307 // for a single file not to be irresolvable obstacle for a status operation 307 // for a single file not to be irresolvable obstacle for a status operation
308 inspector.invalid(r2fname, ex); 308 inspector.invalid(r2fname, ex);
309 } 309 }
310 cs.checkCancelled();
310 } 311 }
311 } 312 }
312 for (Path r1fname : r1Files) { 313 for (Path r1fname : r1Files) {
313 if (scope.accept(r1fname)) { 314 if (scope.accept(r1fname)) {
314 inspector.removed(r1fname); 315 inspector.removed(r1fname);
316 cs.checkCancelled();
315 } 317 }
316 } 318 }
317 } 319 }
318 320
319 /** 321 /**
320 * Collects status between two revisions, changes from <b>rev1</b> up to <b>rev2</b>. 322 * Collects status between two revisions, changes from <b>rev1</b> up to <b>rev2</b>.
321 * 323 *
322 * @param rev1 <em>from</em> changeset index 324 * @param rev1 <em>from</em> changeset index
323 * @param rev2 <em>to</em> changeset index 325 * @param rev2 <em>to</em> changeset index
324 * @return information object that describes change between the revisions 326 * @return information object that describes change between the revisions
325 * @throws HgInvalidRevisionException if any argument specifies non-existent revision index 327 * @throws HgRuntimeException subclass thereof to indicate issues with the library. <em>Runtime exception</em>
326 * @throws HgInvalidControlFileException if access to revlog index/data entry failed
327 */ 328 */
328 public Record status(int rev1, int rev2) throws HgInvalidRevisionException, HgInvalidControlFileException { 329 public Record status(int rev1, int rev2) throws HgInvalidRevisionException, HgInvalidControlFileException {
329 Record rv = new Record(); 330 Record rv = new Record();
330 walk(rev1, rev2, rv); 331 try {
332 walk(rev1, rev2, rv);
333 } catch (CancelledException ex) {
334 // can't happen as long our Record class doesn't implement CancelSupport
335 HgInvalidStateException t = new HgInvalidStateException("Internal error");
336 t.initCause(ex);
337 throw t;
338 }
331 return rv; 339 return rv;
332 } 340 }
333 341
334 /*package-local*/static Path getOriginIfCopy(HgRepository hgRepo, Path fname, Collection<Path> originals, int originalChangelogRevision) throws HgException { 342 /*package-local*/static Path getOriginIfCopy(HgRepository hgRepo, Path fname, Collection<Path> originals, int originalChangelogRevision) throws HgException {
335 HgDataFile df = hgRepo.getFileNode(fname); 343 HgDataFile df = hgRepo.getFileNode(fname);
366 * 374 *
367 * <p>Note, this implementation records copied files as added, thus key values in {@link #getCopied()} map are subset of paths 375 * <p>Note, this implementation records copied files as added, thus key values in {@link #getCopied()} map are subset of paths
368 * from {@link #getAdded()}. 376 * from {@link #getAdded()}.
369 */ 377 */
370 public static class Record implements HgStatusInspector { 378 public static class Record implements HgStatusInspector {
379 // NOTE, shall not implement CancelSupport, or methods that use it and don't expect this exception shall be changed
371 private List<Path> modified, added, removed, clean, missing, unknown, ignored; 380 private List<Path> modified, added, removed, clean, missing, unknown, ignored;
372 private Map<Path, Path> copied; 381 private Map<Path, Path> copied;
373 private Map<Path, Exception> failures; 382 private Map<Path, Exception> failures;
374 383
375 private int startRev, endRev; 384 private int startRev, endRev;