Mercurial > hg4j
diff src/org/tmatesoft/hg/repo/HgManifest.java @ 403:2747b0723867
FIXMEs: work on exceptions and javadoc
author | Artem Tikhomirov <tikhomirov.artem@gmail.com> |
---|---|
date | Mon, 05 Mar 2012 14:50:51 +0100 |
parents | 6952d9ce97f1 |
children | 7f27122011c3 |
line wrap: on
line diff
--- a/src/org/tmatesoft/hg/repo/HgManifest.java Mon Feb 27 19:38:44 2012 +0100 +++ b/src/org/tmatesoft/hg/repo/HgManifest.java Mon Mar 05 14:50:51 2012 +0100 @@ -30,6 +30,7 @@ import org.tmatesoft.hg.core.HgBadStateException; import org.tmatesoft.hg.core.HgException; import org.tmatesoft.hg.core.HgInvalidControlFileException; +import org.tmatesoft.hg.core.HgInvalidRevisionException; import org.tmatesoft.hg.core.Nodeid; import org.tmatesoft.hg.internal.DataAccess; import org.tmatesoft.hg.internal.DigestHelper; @@ -129,9 +130,11 @@ * @param start changelog (not manifest!) revision to begin with * @param end changelog (not manifest!) revision to stop, inclusive. * @param inspector manifest revision visitor, can't be <code>null</code> + * @throws HgInvalidRevisionException if start or end specify non-existent revision index + * @throws IllegalArgumentException if start or end is not a revision index * @throws HgInvalidControlFileException if access to revlog index/data entry failed */ - public void walk(int start, int end, final Inspector inspector) throws /*FIXME HgInvalidRevisionException,*/ HgInvalidControlFileException { + public void walk(int start, int end, final Inspector inspector) throws HgInvalidRevisionException, HgInvalidControlFileException { if (inspector == null) { throw new IllegalArgumentException(); } @@ -139,13 +142,13 @@ int manifestFirst, manifestLast, i = 0; do { manifestFirst = fromChangelog(csetFirst+i); - if (manifestFirst == -1) { + if (manifestFirst == BAD_REVISION) { inspector.begin(BAD_REVISION, NULL, csetFirst+i); inspector.end(BAD_REVISION); } i++; - } while (manifestFirst == -1 && csetFirst+i <= csetLast); - if (manifestFirst == -1) { + } while (manifestFirst == BAD_REVISION && csetFirst+i <= csetLast); + if (manifestFirst == BAD_REVISION) { getRepo().getContext().getLog().info(getClass(), "None of changesets [%d..%d] have associated manifest revision", csetFirst, csetLast); // we ran through all revisions in [start..end] and none of them had manifest. // we reported that to inspector and proceeding is done now. @@ -154,13 +157,13 @@ i = 0; do { manifestLast = fromChangelog(csetLast-i); - if (manifestLast == -1) { + if (manifestLast == BAD_REVISION) { inspector.begin(BAD_REVISION, NULL, csetLast-i); inspector.end(BAD_REVISION); } i++; - } while (manifestLast == -1 && csetLast-i >= csetFirst); - if (manifestLast == -1) { + } while (manifestLast == BAD_REVISION && csetLast-i >= csetFirst); + if (manifestLast == BAD_REVISION) { // hmm, manifestFirst != -1 here, hence there's i from [csetFirst..csetLast] for which manifest entry exists, // and thus it's impossible to run into manifestLast == -1. Nevertheless, never hurts to check. throw new HgBadStateException(String.format("Manifest %d-%d(!) for cset range [%d..%d] ", manifestFirst, manifestLast, csetFirst, csetLast)); @@ -183,8 +186,10 @@ * * @param inspector manifest revision visitor, can't be <code>null</code> * @param revisionIndexes local indexes of changesets to visit, non-<code>null</code> + * @throws HgInvalidRevisionException if argument specifies non-existent revision index + * @throws HgInvalidControlFileException if access to revlog index/data entry failed */ - public void walk(final Inspector inspector, int... revisionIndexes) throws HgInvalidControlFileException{ + public void walk(final Inspector inspector, int... revisionIndexes) throws HgInvalidRevisionException, HgInvalidControlFileException { if (inspector == null || revisionIndexes == null) { throw new IllegalArgumentException(); } @@ -194,10 +199,14 @@ // /** - * Tells manifest revision number that corresponds to the given changeset. - * @return manifest revision index, or -1 if changeset has no associated manifest (cset records NULL nodeid for manifest) + * Tells manifest revision number that corresponds to the given changeset. May return {@link HgRepository#BAD_REVISION} + * if changeset has no associated manifest (cset records NULL nodeid for manifest). + * @return manifest revision index, non-negative, or {@link HgRepository#BAD_REVISION}. + * @throws HgInvalidRevisionException if method argument specifies non-existent revision index + * @throws IllegalArgumentException if argument is not a revision index + * @throws HgInvalidControlFileException if access to revlog index/data entry failed */ - /*package-local*/ int fromChangelog(int changesetRevisionIndex) throws HgInvalidControlFileException { + /*package-local*/ int fromChangelog(int changesetRevisionIndex) throws HgInvalidRevisionException, HgInvalidControlFileException { if (HgInternals.wrongRevisionIndex(changesetRevisionIndex)) { throw new IllegalArgumentException(String.valueOf(changesetRevisionIndex)); } @@ -218,16 +227,18 @@ * @param changelogRevisionIndex local changeset index * @param file path to file in question * @return file revision or <code>null</code> if manifest at specified revision doesn't list such file + * @throws HgInvalidRevisionException if method argument specifies non-existent revision index + * @throws HgInvalidControlFileException if access to revlog index/data entry failed */ @Experimental(reason="Perhaps, HgDataFile shall own this method, or get a delegate?") - public Nodeid getFileRevision(int changelogRevisionIndex, final Path file) throws HgInvalidControlFileException{ + public Nodeid getFileRevision(int changelogRevisionIndex, final Path file) throws HgInvalidRevisionException, HgInvalidControlFileException { return getFileRevisions(file, changelogRevisionIndex).get(changelogRevisionIndex); } // XXX package-local, IntMap, and HgDataFile getFileRevisionAt(int... localChangelogRevisions) @Experimental(reason="@see #getFileRevision") - public Map<Integer, Nodeid> getFileRevisions(final Path file, int... changelogRevisionIndexes) throws HgInvalidControlFileException{ - // FIXME need tests + public Map<Integer, Nodeid> getFileRevisions(final Path file, int... changelogRevisionIndexes) throws HgInvalidRevisionException, HgInvalidControlFileException { + // TODO need tests int[] manifestRevisionIndexes = toManifestRevisionIndexes(changelogRevisionIndexes, null); final HashMap<Integer,Nodeid> rv = new HashMap<Integer, Nodeid>(changelogRevisionIndexes.length); content.iterate(manifestRevisionIndexes, true, new RevlogStream.Inspector() { @@ -267,14 +278,17 @@ /** * @param changelogRevisionIndexes non-null * @param inspector may be null if reporting of missing manifests is not needed + * @throws HgInvalidRevisionException if arguments specify non-existent revision index + * @throws IllegalArgumentException if any index argument is not a revision index + * @throws HgInvalidControlFileException if access to revlog index/data entry failed */ - private int[] toManifestRevisionIndexes(int[] changelogRevisionIndexes, Inspector inspector) throws HgInvalidControlFileException { + private int[] toManifestRevisionIndexes(int[] changelogRevisionIndexes, Inspector inspector) throws HgInvalidRevisionException, HgInvalidControlFileException { int[] manifestRevs = new int[changelogRevisionIndexes.length]; boolean needsSort = false; int j = 0; for (int i = 0; i < changelogRevisionIndexes.length; i++) { final int manifestRevisionIndex = fromChangelog(changelogRevisionIndexes[i]); - if (manifestRevisionIndex == -1) { + if (manifestRevisionIndex == BAD_REVISION) { if (inspector != null) { inspector.begin(BAD_REVISION, NULL, changelogRevisionIndexes[i]); inspector.end(BAD_REVISION); @@ -498,24 +512,32 @@ private static class RevisionMapper implements RevlogStream.Inspector, Lifecycle { - private final int changelogRevisions; + private final int changelogRevisionCount; private int[] changelog2manifest; private final HgRepository repo; public RevisionMapper(HgRepository hgRepo) { repo = hgRepo; - changelogRevisions = repo.getChangelog().getRevisionCount(); + changelogRevisionCount = repo.getChangelog().getRevisionCount(); } - // respects TIP - public int at(int revisionNumber) { - if (revisionNumber == TIP) { - revisionNumber = changelogRevisions - 1; + /** + * Get index of manifest revision that corresponds to specified changeset + * @param changesetRevisionIndex non-negative index of changelog revision, or {@link HgRepository#TIP} + * @return index of manifest revision, or {@link HgRepository#BAD_REVISION} if changeset doesn't reference a valid manifest + * @throws HgInvalidRevisionException if method argument specifies non-existent revision index + */ + public int at(int changesetRevisionIndex) throws HgInvalidRevisionException { + if (changesetRevisionIndex == TIP) { + changesetRevisionIndex = changelogRevisionCount - 1; + } + if (changesetRevisionIndex >= changelogRevisionCount) { + throw new HgInvalidRevisionException(changesetRevisionIndex); } if (changelog2manifest != null) { - return changelog2manifest[revisionNumber]; + return changelog2manifest[changesetRevisionIndex]; } - return revisionNumber; + return changesetRevisionIndex; } // XXX likely can be replaced with Revlog.RevisionInspector @@ -524,12 +546,12 @@ // next assertion is not an error, rather assumption check, which is too development-related to be explicit exception - // I just wonder if there are manifests that have two entries pointing to single changeset. It seems unrealistic, though - // changeset records one and only one manifest nodeid - assert changelog2manifest[linkRevision] == -1 : String.format("revision:%d, link:%d, already linked to revision:%d", revisionNumber, linkRevision, changelog2manifest[linkRevision]); + assert changelog2manifest[linkRevision] == BAD_REVISION : String.format("revision:%d, link:%d, already linked to revision:%d", revisionNumber, linkRevision, changelog2manifest[linkRevision]); changelog2manifest[linkRevision] = revisionNumber; } else { if (revisionNumber != linkRevision) { - changelog2manifest = new int[changelogRevisions]; - Arrays.fill(changelog2manifest, -1); + changelog2manifest = new int[changelogRevisionCount]; + Arrays.fill(changelog2manifest, BAD_REVISION); for (int i = 0; i < revisionNumber; changelog2manifest[i] = i, i++) ; changelog2manifest[linkRevision] = revisionNumber; @@ -538,14 +560,14 @@ } public void start(int count, Callback callback, Object token) { - if (count != changelogRevisions) { - assert count < changelogRevisions; // no idea what to do if manifest has more revisions than changelog + if (count != changelogRevisionCount) { + assert count < changelogRevisionCount; // no idea what to do if manifest has more revisions than changelog // the way how manifest may contain more revisions than changelog, as I can imagine, is a result of // some kind of an import tool (e.g. from SVN or CVS), that creates manifest and changelog independently. // Note, it's pure guess, I didn't see such repository yet (although the way manifest revisions // in cpython repo are numbered makes me think aforementioned way) - changelog2manifest = new int[changelogRevisions]; - Arrays.fill(changelog2manifest, -1); + changelog2manifest = new int[changelogRevisionCount]; + Arrays.fill(changelog2manifest, BAD_REVISION); } } @@ -556,7 +578,7 @@ // I assume there'd be not too many revisions we don't know manifest of ArrayList<Integer> undefinedChangelogRevision = new ArrayList<Integer>(); for (int i = 0; i < changelog2manifest.length; i++) { - if (changelog2manifest[i] == -1) { + if (changelog2manifest[i] == BAD_REVISION) { undefinedChangelogRevision.add(i); } }