Mercurial > jhg
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) { | 
