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 }