Mercurial > jhg
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 } | 
