Mercurial > hg4j
comparison src/org/tmatesoft/hg/repo/HgManifest.java @ 628:6526d8adbc0f
Explicit HgRuntimeException to facilitate easy switch from runtime to checked exceptions
| author | Artem Tikhomirov <tikhomirov.artem@gmail.com> |
|---|---|
| date | Wed, 22 May 2013 15:52:31 +0200 |
| parents | e1b29756f901 |
| children | 8a5cdcb27b8f |
comparison
equal
deleted
inserted
replaced
| 627:5153eb73b18d | 628:6526d8adbc0f |
|---|---|
| 235 * gets invoked doesn't resemble order of changeset revisions supplied, manifest revisions are reported in the order they appear | 235 * gets invoked doesn't resemble order of changeset revisions supplied, manifest revisions are reported in the order they appear |
| 236 * in manifest revlog (with exception of changesets with missing manifest that may be reported in any order). | 236 * in manifest revlog (with exception of changesets with missing manifest that may be reported in any order). |
| 237 * | 237 * |
| 238 * @param inspector manifest revision visitor, can't be <code>null</code> | 238 * @param inspector manifest revision visitor, can't be <code>null</code> |
| 239 * @param revisionIndexes local indexes of changesets to visit, non-<code>null</code> | 239 * @param revisionIndexes local indexes of changesets to visit, non-<code>null</code> |
| 240 * @throws HgRuntimeException subclass thereof to indicate issues with the library. <em>Runtime exception</em> | 240 * @throws HgInvalidRevisionException if method argument specifies non-existent revision index. <em>Runtime exception</em> |
| 241 * @throws HgInvalidControlFileException if failed to access revlog index/data entry. <em>Runtime exception</em> | |
| 242 * @throws HgRuntimeException subclass thereof to indicate other issues with the library. <em>Runtime exception</em> | |
| 241 * @throws InvalidArgumentException if supplied arguments are <code>null</code>s | 243 * @throws InvalidArgumentException if supplied arguments are <code>null</code>s |
| 242 */ | 244 */ |
| 243 public void walk(final Inspector inspector, int... revisionIndexes) throws HgRuntimeException, IllegalArgumentException { | 245 public void walk(final Inspector inspector, int... revisionIndexes) throws HgRuntimeException, IllegalArgumentException { |
| 244 if (inspector == null || revisionIndexes == null) { | 246 if (inspector == null || revisionIndexes == null) { |
| 245 throw new IllegalArgumentException(); | 247 throw new IllegalArgumentException(); |
| 251 // | 253 // |
| 252 /** | 254 /** |
| 253 * Tells manifest revision number that corresponds to the given changeset. May return {@link HgRepository#BAD_REVISION} | 255 * Tells manifest revision number that corresponds to the given changeset. May return {@link HgRepository#BAD_REVISION} |
| 254 * if changeset has no associated manifest (cset records NULL nodeid for manifest). | 256 * if changeset has no associated manifest (cset records NULL nodeid for manifest). |
| 255 * @return manifest revision index, non-negative, or {@link HgRepository#BAD_REVISION}. | 257 * @return manifest revision index, non-negative, or {@link HgRepository#BAD_REVISION}. |
| 256 * @throws HgInvalidRevisionException if method argument specifies non-existent revision index | 258 * @throws HgInvalidRevisionException if method argument specifies non-existent revision index. <em>Runtime exception</em> |
| 257 * @throws HgInvalidControlFileException if access to revlog index/data entry failed | 259 * @throws HgInvalidControlFileException if failed to access revlog index/data entry. <em>Runtime exception</em> |
| 258 */ | 260 * @throws HgRuntimeException subclass thereof to indicate other issues with the library. <em>Runtime exception</em> |
| 259 /*package-local*/ int fromChangelog(int changesetRevisionIndex) throws HgInvalidRevisionException, HgInvalidControlFileException { | 261 */ |
| 262 /*package-local*/ int fromChangelog(int changesetRevisionIndex) throws HgRuntimeException { | |
| 260 if (HgInternals.wrongRevisionIndex(changesetRevisionIndex)) { | 263 if (HgInternals.wrongRevisionIndex(changesetRevisionIndex)) { |
| 261 throw new HgInvalidRevisionException(changesetRevisionIndex); | 264 throw new HgInvalidRevisionException(changesetRevisionIndex); |
| 262 } | 265 } |
| 263 if (changesetRevisionIndex == HgRepository.WORKING_COPY || changesetRevisionIndex == HgRepository.BAD_REVISION) { | 266 if (changesetRevisionIndex == HgRepository.WORKING_COPY || changesetRevisionIndex == HgRepository.BAD_REVISION) { |
| 264 throw new HgInvalidRevisionException("Can't use constants like WORKING_COPY or BAD_REVISION", null, changesetRevisionIndex); | 267 throw new HgInvalidRevisionException("Can't use constants like WORKING_COPY or BAD_REVISION", null, changesetRevisionIndex); |
| 294 * @see #walkFileRevisions(Path, Inspector, int...) | 297 * @see #walkFileRevisions(Path, Inspector, int...) |
| 295 * @see HgChangesetFileSneaker | 298 * @see HgChangesetFileSneaker |
| 296 * @param changelogRevisionIndex local changeset index | 299 * @param changelogRevisionIndex local changeset index |
| 297 * @param file path to file in question | 300 * @param file path to file in question |
| 298 * @return file revision or <code>null</code> if manifest at specified revision doesn't list such file | 301 * @return file revision or <code>null</code> if manifest at specified revision doesn't list such file |
| 299 * @throws HgRuntimeException subclass thereof to indicate issues with the library. <em>Runtime exception</em> | 302 * @throws HgInvalidRevisionException if supplied revision doesn't identify revision from this revlog. <em>Runtime exception</em> |
| 300 */ | 303 * @throws HgInvalidControlFileException if failed to access revlog index/data entry. <em>Runtime exception</em> |
| 301 public Nodeid getFileRevision(int changelogRevisionIndex, final Path file) throws HgInvalidRevisionException, HgInvalidControlFileException { | 304 * @throws HgRuntimeException subclass thereof to indicate other issues with the library. <em>Runtime exception</em> |
| 305 */ | |
| 306 public Nodeid getFileRevision(int changelogRevisionIndex, final Path file) throws HgRuntimeException { | |
| 302 // there's no need for HgDataFile to own this method, or get a delegate | 307 // there's no need for HgDataFile to own this method, or get a delegate |
| 303 // as most of HgDataFile API is using file revision indexes, and there's easy step from file revision index to | 308 // as most of HgDataFile API is using file revision indexes, and there's easy step from file revision index to |
| 304 // both file revision and changeset revision index. But there's no easy way to go from changesetRevisionIndex to | 309 // both file revision and changeset revision index. But there's no easy way to go from changesetRevisionIndex to |
| 305 // file revision (the task this method solves), except for HgFileInformer | 310 // file revision (the task this method solves), except for HgFileInformer |
| 306 // I feel methods dealing with changeset indexes shall be more exposed in HgChangelog and HgManifest API. | 311 // I feel methods dealing with changeset indexes shall be more exposed in HgChangelog and HgManifest API. |
| 328 * | 333 * |
| 329 * @see #getFileRevision(int, Path) | 334 * @see #getFileRevision(int, Path) |
| 330 * @param file path of interest | 335 * @param file path of interest |
| 331 * @param inspector callback to receive details about selected file | 336 * @param inspector callback to receive details about selected file |
| 332 * @param changelogRevisionIndexes changeset indexes to visit | 337 * @param changelogRevisionIndexes changeset indexes to visit |
| 333 * @throws HgRuntimeException subclass thereof to indicate issues with the library. <em>Runtime exception</em> | 338 * @throws HgInvalidRevisionException if supplied revision doesn't identify revision from this revlog. <em>Runtime exception</em> |
| 339 * @throws HgInvalidControlFileException if failed to access revlog index/data entry. <em>Runtime exception</em> | |
| 340 * @throws HgRuntimeException subclass thereof to indicate other issues with the library. <em>Runtime exception</em> | |
| 334 */ | 341 */ |
| 335 public void walkFileRevisions(Path file, Inspector inspector, int... changelogRevisionIndexes) throws HgRuntimeException { | 342 public void walkFileRevisions(Path file, Inspector inspector, int... changelogRevisionIndexes) throws HgRuntimeException { |
| 336 if (file == null || inspector == null || changelogRevisionIndexes == null) { | 343 if (file == null || inspector == null || changelogRevisionIndexes == null) { |
| 337 throw new IllegalArgumentException(); | 344 throw new IllegalArgumentException(); |
| 338 } | 345 } |
| 347 * | 354 * |
| 348 * @see HgDataFile#getFlags(int) | 355 * @see HgDataFile#getFlags(int) |
| 349 * @param changesetRevIndex changeset revision index | 356 * @param changesetRevIndex changeset revision index |
| 350 * @param file path to look up | 357 * @param file path to look up |
| 351 * @return one of predefined enum values, or <code>null</code> if file was not known in the specified revision | 358 * @return one of predefined enum values, or <code>null</code> if file was not known in the specified revision |
| 352 * @throws HgRuntimeException subclass thereof to indicate issues with the library. <em>Runtime exception</em> | 359 * @throws HgInvalidRevisionException if supplied revision doesn't identify revision from this revlog. <em>Runtime exception</em> |
| 353 */ | 360 * @throws HgInvalidControlFileException if failed to access revlog index/data entry. <em>Runtime exception</em> |
| 354 public Flags getFileFlags(int changesetRevIndex, Path file) throws HgInvalidRevisionException, HgInvalidControlFileException { | 361 * @throws HgRuntimeException subclass thereof to indicate other issues with the library. <em>Runtime exception</em> |
| 362 */ | |
| 363 public Flags getFileFlags(int changesetRevIndex, Path file) throws HgRuntimeException { | |
| 355 int manifestRevIdx = fromChangelog(changesetRevIndex); | 364 int manifestRevIdx = fromChangelog(changesetRevIndex); |
| 356 IntMap<Flags> resMap = new IntMap<Flags>(2); | 365 IntMap<Flags> resMap = new IntMap<Flags>(2); |
| 357 FileLookupInspector parser = new FileLookupInspector(encodingHelper, file, null, resMap); | 366 FileLookupInspector parser = new FileLookupInspector(encodingHelper, file, null, resMap); |
| 358 parser.walk(manifestRevIdx, content); | 367 parser.walk(manifestRevIdx, content); |
| 359 assert resMap.size() <= 1; // size() == 0 if not found | 368 assert resMap.size() <= 1; // size() == 0 if not found |
| 372 } | 381 } |
| 373 | 382 |
| 374 /** | 383 /** |
| 375 * @param changelogRevisionIndexes non-null | 384 * @param changelogRevisionIndexes non-null |
| 376 * @param inspector may be null if reporting of missing manifests is not needed | 385 * @param inspector may be null if reporting of missing manifests is not needed |
| 377 * @throws HgInvalidRevisionException if arguments specify non-existent revision index | 386 * @throws HgInvalidRevisionException if supplied revision doesn't identify revision from this revlog. <em>Runtime exception</em> |
| 378 * @throws IllegalArgumentException if any index argument is not a revision index | 387 * @throws HgInvalidControlFileException if failed to access revlog index/data entry. <em>Runtime exception</em> |
| 379 * @throws HgInvalidControlFileException if access to revlog index/data entry failed | 388 * @throws HgRuntimeException subclass thereof to indicate other issues with the library. <em>Runtime exception</em> |
| 380 */ | 389 */ |
| 381 private int[] toManifestRevisionIndexes(int[] changelogRevisionIndexes, Inspector inspector) throws HgInvalidRevisionException, HgInvalidControlFileException { | 390 private int[] toManifestRevisionIndexes(int[] changelogRevisionIndexes, Inspector inspector) throws HgRuntimeException { |
| 382 int[] manifestRevs = new int[changelogRevisionIndexes.length]; | 391 int[] manifestRevs = new int[changelogRevisionIndexes.length]; |
| 383 boolean needsSort = false; | 392 boolean needsSort = false; |
| 384 int j = 0; | 393 int j = 0; |
| 385 for (int i = 0; i < changelogRevisionIndexes.length; i++) { | 394 for (int i = 0; i < changelogRevisionIndexes.length; i++) { |
| 386 final int manifestRevisionIndex = fromChangelog(changelogRevisionIndexes[i]); | 395 final int manifestRevisionIndex = fromChangelog(changelogRevisionIndexes[i]); |
| 419 * | 428 * |
| 420 * @param manifestRevisionIndex local revision index of the inspected revision | 429 * @param manifestRevisionIndex local revision index of the inspected revision |
| 421 * @param manifestRevision revision of the manifest we're about to iterate through | 430 * @param manifestRevision revision of the manifest we're about to iterate through |
| 422 * @param changelogRevisionIndex local revision index of changelog this manifest points to | 431 * @param changelogRevisionIndex local revision index of changelog this manifest points to |
| 423 * @return <code>true</code> to continue iteration, <code>false</code> to stop | 432 * @return <code>true</code> to continue iteration, <code>false</code> to stop |
| 433 * @throws HgRuntimeException propagates library issues. <em>Runtime exception</em> | |
| 424 */ | 434 */ |
| 425 boolean begin(int manifestRevisionIndex, Nodeid manifestRevision, int changelogRevisionIndex); | 435 boolean begin(int manifestRevisionIndex, Nodeid manifestRevision, int changelogRevisionIndex) throws HgRuntimeException; |
| 426 | 436 |
| 427 | 437 |
| 428 /** | 438 /** |
| 429 * Reports each manifest entry | 439 * Reports each manifest entry |
| 430 * | 440 * |
| 431 * @param nid file revision | 441 * @param nid file revision |
| 432 * @param fname file name | 442 * @param fname file name |
| 433 * @param flags one of {@link HgManifest.Flags} constants, not <code>null</code> | 443 * @param flags one of {@link HgManifest.Flags} constants, not <code>null</code> |
| 434 * @return <code>true</code> to continue iteration, <code>false</code> to stop | 444 * @return <code>true</code> to continue iteration, <code>false</code> to stop |
| 445 * @throws HgRuntimeException propagates library issues. <em>Runtime exception</em> | |
| 435 */ | 446 */ |
| 436 boolean next(Nodeid nid, Path fname, Flags flags); | 447 boolean next(Nodeid nid, Path fname, Flags flags) throws HgRuntimeException; |
| 437 | 448 |
| 438 /** | 449 /** |
| 439 * Denotes leaving specific manifest revision, after all entries were reported using {@link #next(Nodeid, Path, Flags)} | 450 * Denotes leaving specific manifest revision, after all entries were reported using {@link #next(Nodeid, Path, Flags)} |
| 440 * | 451 * |
| 441 * @param manifestRevisionIndex indicates manifest revision, corresponds to opening {@link #begin(int, Nodeid, int)} | 452 * @param manifestRevisionIndex indicates manifest revision, corresponds to opening {@link #begin(int, Nodeid, int)} |
| 442 * @return <code>true</code> to continue iteration, <code>false</code> to stop | 453 * @return <code>true</code> to continue iteration, <code>false</code> to stop |
| 454 * @throws HgRuntimeException propagates library issues. <em>Runtime exception</em> | |
| 443 */ | 455 */ |
| 444 boolean end(int manifestRevisionIndex); | 456 boolean end(int manifestRevisionIndex) throws HgRuntimeException; |
| 445 } | 457 } |
| 446 | 458 |
| 447 /** | 459 /** |
| 448 * When Pool uses Strings directly, | 460 * When Pool uses Strings directly, |
| 449 * ManifestParser creates new String instance with new char[] value, and does byte->char conversion. | 461 * ManifestParser creates new String instance with new char[] value, and does byte->char conversion. |
| 529 fnamePool = new IdentityPool<PathProxy>(); | 541 fnamePool = new IdentityPool<PathProxy>(); |
| 530 thisRevPool = new IdentityPool<Nodeid>(); | 542 thisRevPool = new IdentityPool<Nodeid>(); |
| 531 progressHelper = ProgressSupport.Factory.get(delegate); | 543 progressHelper = ProgressSupport.Factory.get(delegate); |
| 532 } | 544 } |
| 533 | 545 |
| 534 public void next(int revisionNumber, int actualLen, int baseRevision, int linkRevision, int parent1Revision, int parent2Revision, byte[] nodeid, DataAccess da) { | 546 public void next(int revisionNumber, int actualLen, int baseRevision, int linkRevision, int parent1Revision, int parent2Revision, byte[] nodeid, DataAccess da) throws HgRuntimeException { |
| 535 try { | 547 try { |
| 536 if (!inspector.begin(revisionNumber, new Nodeid(nodeid, true), linkRevision)) { | 548 if (!inspector.begin(revisionNumber, new Nodeid(nodeid, true), linkRevision)) { |
| 537 iterateControl.stop(); | 549 iterateControl.stop(); |
| 538 return; | 550 return; |
| 539 } | 551 } |
| 621 | 633 |
| 622 private final int changelogRevisionCount; | 634 private final int changelogRevisionCount; |
| 623 private int[] changelog2manifest; | 635 private int[] changelog2manifest; |
| 624 RevisionLookup manifestNodeids; | 636 RevisionLookup manifestNodeids; |
| 625 | 637 |
| 626 private RevisionMapper(boolean useOwnRevisionLookup) { | 638 private RevisionMapper(boolean useOwnRevisionLookup) throws HgRuntimeException { |
| 627 changelogRevisionCount = HgManifest.this.getRepo().getChangelog().getRevisionCount(); | 639 changelogRevisionCount = HgManifest.this.getRepo().getChangelog().getRevisionCount(); |
| 628 if (useOwnRevisionLookup) { | 640 if (useOwnRevisionLookup) { |
| 629 manifestNodeids = new RevisionLookup(HgManifest.this.content); | 641 manifestNodeids = new RevisionLookup(HgManifest.this.content); |
| 630 } | 642 } |
| 631 } | 643 } |
| 689 public void finish(Object token) { | 701 public void finish(Object token) { |
| 690 // it's not a nice idea to fix changesets that reuse existing manifest entries from inside | 702 // it's not a nice idea to fix changesets that reuse existing manifest entries from inside |
| 691 // #finish, as the manifest read operation is not complete at the moment. | 703 // #finish, as the manifest read operation is not complete at the moment. |
| 692 } | 704 } |
| 693 | 705 |
| 694 public void fixReusedManifests() { | 706 public void fixReusedManifests() throws HgRuntimeException { |
| 695 if (changelog2manifest == null) { | 707 if (changelog2manifest == null) { |
| 696 // direct, 1-1 mapping of changeset indexes to manifest | 708 // direct, 1-1 mapping of changeset indexes to manifest |
| 697 return; | 709 return; |
| 698 } | 710 } |
| 699 // I assume there'd be not too many revisions we don't know manifest of | 711 // I assume there'd be not too many revisions we don't know manifest of |
| 766 delegate = delegateInspector; | 778 delegate = delegateInspector; |
| 767 csetIndex2FileRev = null; | 779 csetIndex2FileRev = null; |
| 768 csetIndex2Flags = null; | 780 csetIndex2Flags = null; |
| 769 } | 781 } |
| 770 | 782 |
| 771 void walk(int manifestRevIndex, RevlogStream content) { | 783 void walk(int manifestRevIndex, RevlogStream content) throws HgRuntimeException { |
| 772 content.iterate(manifestRevIndex, manifestRevIndex, true, this); | 784 content.iterate(manifestRevIndex, manifestRevIndex, true, this); |
| 773 } | 785 } |
| 774 | 786 |
| 775 void walk(int[] manifestRevIndexes, RevlogStream content) { | 787 void walk(int[] manifestRevIndexes, RevlogStream content) throws HgRuntimeException { |
| 776 content.iterate(manifestRevIndexes, true, this); | 788 content.iterate(manifestRevIndexes, true, this); |
| 777 } | 789 } |
| 778 | 790 |
| 779 public void next(int revisionNumber, int actualLen, int baseRevision, int linkRevision, int parent1Revision, int parent2Revision, byte[] nodeid, DataAccess data) { | 791 public void next(int revisionNumber, int actualLen, int baseRevision, int linkRevision, int parent1Revision, int parent2Revision, byte[] nodeid, DataAccess data) throws HgRuntimeException { |
| 780 ByteVector byteVector = new ByteVector(256, 128); // allocate for long paths right away | 792 ByteVector byteVector = new ByteVector(256, 128); // allocate for long paths right away |
| 781 try { | 793 try { |
| 782 byte b; | 794 byte b; |
| 783 while (!data.isEmpty() && (b = data.readByte()) != '\n') { | 795 while (!data.isEmpty() && (b = data.readByte()) != '\n') { |
| 784 if (b != 0) { | 796 if (b != 0) { |
