Mercurial > hg4j
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; |
