Mercurial > hg4j
comparison src/org/tmatesoft/hg/repo/HgManifest.java @ 366:189dc6dc1c3e
Use exceptions to expose errors reading mercurial data
| author | Artem Tikhomirov <tikhomirov.artem@gmail.com> |
|---|---|
| date | Fri, 16 Dec 2011 04:43:18 +0100 |
| parents | 5f9073eabf06 |
| children | 2fadf8695f8a |
comparison
equal
deleted
inserted
replaced
| 365:3572fcb06473 | 366:189dc6dc1c3e |
|---|---|
| 23 import java.util.ArrayList; | 23 import java.util.ArrayList; |
| 24 import java.util.Arrays; | 24 import java.util.Arrays; |
| 25 import java.util.HashMap; | 25 import java.util.HashMap; |
| 26 import java.util.Map; | 26 import java.util.Map; |
| 27 | 27 |
| 28 import org.tmatesoft.hg.core.HgBadStateException; | 28 import org.tmatesoft.hg.core.HgException; |
| 29 import org.tmatesoft.hg.core.HgInvalidControlFileException; | 29 import org.tmatesoft.hg.core.HgInvalidControlFileException; |
| 30 import org.tmatesoft.hg.core.Nodeid; | 30 import org.tmatesoft.hg.core.Nodeid; |
| 31 import org.tmatesoft.hg.internal.DataAccess; | 31 import org.tmatesoft.hg.internal.DataAccess; |
| 32 import org.tmatesoft.hg.internal.DigestHelper; | 32 import org.tmatesoft.hg.internal.DigestHelper; |
| 33 import org.tmatesoft.hg.internal.EncodingHelper; | 33 import org.tmatesoft.hg.internal.EncodingHelper; |
| 100 * | 100 * |
| 101 * @param start changelog (not manifest!) revision to begin with | 101 * @param start changelog (not manifest!) revision to begin with |
| 102 * @param end changelog (not manifest!) revision to stop, inclusive. | 102 * @param end changelog (not manifest!) revision to stop, inclusive. |
| 103 * @param inspector can't be <code>null</code> | 103 * @param inspector can't be <code>null</code> |
| 104 */ | 104 */ |
| 105 public void walk(int start, int end, final Inspector inspector) { | 105 public void walk(int start, int end, final Inspector inspector) throws /*FIXME HgInvalidRevisionException,*/ HgInvalidControlFileException { |
| 106 if (inspector == null) { | 106 if (inspector == null) { |
| 107 throw new IllegalArgumentException(); | 107 throw new IllegalArgumentException(); |
| 108 } | 108 } |
| 109 int start0 = fromChangelog(start); | 109 int start0 = fromChangelog(start); |
| 110 int end0 = fromChangelog(end); | 110 int end0 = fromChangelog(end); |
| 121 * "Sparse" iteration of the manifest | 121 * "Sparse" iteration of the manifest |
| 122 * | 122 * |
| 123 * @param inspector | 123 * @param inspector |
| 124 * @param localRevisions local changeset revisions to visit | 124 * @param localRevisions local changeset revisions to visit |
| 125 */ | 125 */ |
| 126 public void walk(final Inspector inspector, int... localRevisions) { | 126 public void walk(final Inspector inspector, int... localRevisions) throws HgInvalidControlFileException{ |
| 127 if (inspector == null || localRevisions == null) { | 127 if (inspector == null || localRevisions == null) { |
| 128 throw new IllegalArgumentException(); | 128 throw new IllegalArgumentException(); |
| 129 } | 129 } |
| 130 int[] localManifestRevs = toLocalManifestRevisions(localRevisions); | 130 int[] localManifestRevs = toLocalManifestRevisions(localRevisions); |
| 131 content.iterate(localManifestRevs, true, new ManifestParser(inspector)); | 131 content.iterate(localManifestRevs, true, new ManifestParser(inspector)); |
| 132 } | 132 } |
| 133 | 133 |
| 134 // manifest revision number that corresponds to the given changeset | 134 // manifest revision number that corresponds to the given changeset |
| 135 /*package-local*/ int fromChangelog(int revisionNumber) { | 135 /*package-local*/ int fromChangelog(int revisionNumber) throws HgInvalidControlFileException { |
| 136 if (HgInternals.wrongLocalRevision(revisionNumber)) { | 136 if (HgInternals.wrongLocalRevision(revisionNumber)) { |
| 137 throw new IllegalArgumentException(String.valueOf(revisionNumber)); | 137 throw new IllegalArgumentException(String.valueOf(revisionNumber)); |
| 138 } | 138 } |
| 139 if (revisionNumber == HgRepository.WORKING_COPY || revisionNumber == HgRepository.BAD_REVISION) { | 139 if (revisionNumber == HgRepository.WORKING_COPY || revisionNumber == HgRepository.BAD_REVISION) { |
| 140 throw new IllegalArgumentException("Can't use constants like WORKING_COPY or BAD_REVISION"); | 140 throw new IllegalArgumentException("Can't use constants like WORKING_COPY or BAD_REVISION"); |
| 153 * @param localChangelogRevision local changeset index | 153 * @param localChangelogRevision local changeset index |
| 154 * @param file path to file in question | 154 * @param file path to file in question |
| 155 * @return file revision or <code>null</code> if manifest at specified revision doesn't list such file | 155 * @return file revision or <code>null</code> if manifest at specified revision doesn't list such file |
| 156 */ | 156 */ |
| 157 @Experimental(reason="Perhaps, HgDataFile shall own this method, or get a delegate?") | 157 @Experimental(reason="Perhaps, HgDataFile shall own this method, or get a delegate?") |
| 158 public Nodeid getFileRevision(int localChangelogRevision, final Path file) { | 158 public Nodeid getFileRevision(int localChangelogRevision, final Path file) throws HgInvalidControlFileException{ |
| 159 return getFileRevisions(file, localChangelogRevision).get(localChangelogRevision); | 159 return getFileRevisions(file, localChangelogRevision).get(localChangelogRevision); |
| 160 } | 160 } |
| 161 | 161 |
| 162 // XXX package-local, IntMap, and HgDataFile getFileRevisionAt(int... localChangelogRevisions) | 162 // XXX package-local, IntMap, and HgDataFile getFileRevisionAt(int... localChangelogRevisions) |
| 163 @Experimental(reason="@see #getFileRevision") | 163 @Experimental(reason="@see #getFileRevision") |
| 164 public Map<Integer, Nodeid> getFileRevisions(final Path file, int... localChangelogRevisions) { | 164 public Map<Integer, Nodeid> getFileRevisions(final Path file, int... localChangelogRevisions) throws HgInvalidControlFileException{ |
| 165 // FIXME need tests | 165 // FIXME need tests |
| 166 int[] localManifestRevisions = toLocalManifestRevisions(localChangelogRevisions); | 166 int[] localManifestRevisions = toLocalManifestRevisions(localChangelogRevisions); |
| 167 final HashMap<Integer,Nodeid> rv = new HashMap<Integer, Nodeid>(localChangelogRevisions.length); | 167 final HashMap<Integer,Nodeid> rv = new HashMap<Integer, Nodeid>(localChangelogRevisions.length); |
| 168 content.iterate(localManifestRevisions, true, new RevlogStream.Inspector() { | 168 content.iterate(localManifestRevisions, true, new RevlogStream.Inspector() { |
| 169 | 169 |
| 170 public void next(int revisionNumber, int actualLen, int baseRevision, int linkRevision, int parent1Revision, int parent2Revision, byte[] nodeid, DataAccess data) { | 170 public void next(int revisionNumber, int actualLen, int baseRevision, int linkRevision, int parent1Revision, int parent2Revision, byte[] nodeid, DataAccess data) throws HgException { |
| 171 ByteArrayOutputStream bos = new ByteArrayOutputStream(); | 171 ByteArrayOutputStream bos = new ByteArrayOutputStream(); |
| 172 try { | 172 try { |
| 173 byte b; | 173 byte b; |
| 174 while (!data.isEmpty() && (b = data.readByte()) != '\n') { | 174 while (!data.isEmpty() && (b = data.readByte()) != '\n') { |
| 175 if (b != 0) { | 175 if (b != 0) { |
| 189 while (!data.isEmpty() && (b = data.readByte()) != '\n') | 189 while (!data.isEmpty() && (b = data.readByte()) != '\n') |
| 190 ; | 190 ; |
| 191 } | 191 } |
| 192 } | 192 } |
| 193 } catch (IOException ex) { | 193 } catch (IOException ex) { |
| 194 throw new HgBadStateException(ex); | 194 throw new HgException(ex); |
| 195 } | 195 } |
| 196 } | 196 } |
| 197 }); | 197 }); |
| 198 return rv; | 198 return rv; |
| 199 } | 199 } |
| 200 | 200 |
| 201 | 201 |
| 202 private int[] toLocalManifestRevisions(int[] localChangelogRevisions) { | 202 private int[] toLocalManifestRevisions(int[] localChangelogRevisions) throws HgInvalidControlFileException { |
| 203 int[] localManifestRevs = new int[localChangelogRevisions.length]; | 203 int[] localManifestRevs = new int[localChangelogRevisions.length]; |
| 204 boolean needsSort = false; | 204 boolean needsSort = false; |
| 205 for (int i = 0; i < localChangelogRevisions.length; i++) { | 205 for (int i = 0; i < localChangelogRevisions.length; i++) { |
| 206 final int manifestLocalRev = fromChangelog(localChangelogRevisions[i]); | 206 final int manifestLocalRev = fromChangelog(localChangelogRevisions[i]); |
| 207 localManifestRevs[i] = manifestLocalRev; | 207 localManifestRevs[i] = manifestLocalRev; |
| 316 fnamePool = new Pool2<PathProxy>(); | 316 fnamePool = new Pool2<PathProxy>(); |
| 317 thisRevPool = new Pool2<Nodeid>(); | 317 thisRevPool = new Pool2<Nodeid>(); |
| 318 progressHelper = ProgressSupport.Factory.get(delegate); | 318 progressHelper = ProgressSupport.Factory.get(delegate); |
| 319 } | 319 } |
| 320 | 320 |
| 321 public void next(int revisionNumber, int actualLen, int baseRevision, int linkRevision, int parent1Revision, int parent2Revision, byte[] nodeid, DataAccess da) { | 321 public void next(int revisionNumber, int actualLen, int baseRevision, int linkRevision, int parent1Revision, int parent2Revision, byte[] nodeid, DataAccess da) throws HgException { |
| 322 try { | 322 try { |
| 323 if (!inspector.begin(revisionNumber, new Nodeid(nodeid, true), linkRevision)) { | 323 if (!inspector.begin(revisionNumber, new Nodeid(nodeid, true), linkRevision)) { |
| 324 iterateControl.stop(); | 324 iterateControl.stop(); |
| 325 return; | 325 return; |
| 326 } | 326 } |
| 390 nodeidPool = thisRevPool; | 390 nodeidPool = thisRevPool; |
| 391 thisRevPool = t; | 391 thisRevPool = t; |
| 392 iterateControl.checkCancelled(); | 392 iterateControl.checkCancelled(); |
| 393 progressHelper.worked(1); | 393 progressHelper.worked(1); |
| 394 } catch (IOException ex) { | 394 } catch (IOException ex) { |
| 395 throw new HgBadStateException(ex); | 395 throw new HgException(ex); |
| 396 } | 396 } |
| 397 } | 397 } |
| 398 | 398 |
| 399 public void start(int count, Callback callback, Object token) { | 399 public void start(int count, Callback callback, Object token) { |
| 400 CancelSupport cs = CancelSupport.Factory.get(inspector, null); | 400 CancelSupport cs = CancelSupport.Factory.get(inspector, null); |
| 470 if (changelog2manifest[i] == -1) { | 470 if (changelog2manifest[i] == -1) { |
| 471 undefinedChangelogRevision.add(i); | 471 undefinedChangelogRevision.add(i); |
| 472 } | 472 } |
| 473 } | 473 } |
| 474 for (int u : undefinedChangelogRevision) { | 474 for (int u : undefinedChangelogRevision) { |
| 475 Nodeid manifest = repo.getChangelog().range(u, u).get(0).manifest(); | |
| 476 // FIXME calculate those missing effectively (e.g. cache and sort nodeids to speed lookup | |
| 477 // right away in the #next (may refactor ParentWalker's sequential and sorted into dedicated helper and reuse here) | |
| 478 try { | 475 try { |
| 476 Nodeid manifest = repo.getChangelog().range(u, u).get(0).manifest(); | |
| 477 // FIXME calculate those missing effectively (e.g. cache and sort nodeids to speed lookup | |
| 478 // right away in the #next (may refactor ParentWalker's sequential and sorted into dedicated helper and reuse here) | |
| 479 changelog2manifest[u] = repo.getManifest().getLocalRevision(manifest); | 479 changelog2manifest[u] = repo.getManifest().getLocalRevision(manifest); |
| 480 } catch (HgInvalidControlFileException ex) { | 480 } catch (HgInvalidControlFileException ex) { |
| 481 // FIXME need to propagate the error up to client | 481 // FIXME need to propagate the error up to client |
| 482 repo.getContext().getLog().error(getClass(), ex, null); | 482 repo.getContext().getLog().error(getClass(), ex, null); |
| 483 } | 483 } |
