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