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