Mercurial > jhg
comparison src/org/tmatesoft/hg/repo/HgChangelog.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 | 3572fcb06473 |
| children | 2fadf8695f8a |
comparison
equal
deleted
inserted
replaced
| 365:3572fcb06473 | 366:189dc6dc1c3e |
|---|---|
| 29 import java.util.List; | 29 import java.util.List; |
| 30 import java.util.Locale; | 30 import java.util.Locale; |
| 31 import java.util.Map; | 31 import java.util.Map; |
| 32 import java.util.TimeZone; | 32 import java.util.TimeZone; |
| 33 | 33 |
| 34 import org.tmatesoft.hg.core.HgBadStateException; | 34 import org.tmatesoft.hg.core.HgBadArgumentException; |
| 35 import org.tmatesoft.hg.core.HgException; | |
| 35 import org.tmatesoft.hg.core.HgInvalidControlFileException; | 36 import org.tmatesoft.hg.core.HgInvalidControlFileException; |
| 36 import org.tmatesoft.hg.core.HgInvalidRevisionException; | 37 import org.tmatesoft.hg.core.HgInvalidRevisionException; |
| 37 import org.tmatesoft.hg.core.Nodeid; | 38 import org.tmatesoft.hg.core.Nodeid; |
| 38 import org.tmatesoft.hg.internal.DataAccess; | 39 import org.tmatesoft.hg.internal.DataAccess; |
| 39 import org.tmatesoft.hg.internal.IterateControlMediator; | 40 import org.tmatesoft.hg.internal.IterateControlMediator; |
| 54 | 55 |
| 55 /* package-local */HgChangelog(HgRepository hgRepo, RevlogStream content) { | 56 /* package-local */HgChangelog(HgRepository hgRepo, RevlogStream content) { |
| 56 super(hgRepo, content); | 57 super(hgRepo, content); |
| 57 } | 58 } |
| 58 | 59 |
| 59 public void all(final HgChangelog.Inspector inspector) throws HgInvalidRevisionException { | 60 public void all(final HgChangelog.Inspector inspector) throws HgInvalidRevisionException, HgInvalidControlFileException { |
| 60 range(0, getLastRevision(), inspector); | 61 range(0, getLastRevision(), inspector); |
| 61 } | 62 } |
| 62 | 63 |
| 63 public void range(int start, int end, final HgChangelog.Inspector inspector) throws HgInvalidRevisionException { | 64 public void range(int start, int end, final HgChangelog.Inspector inspector) throws HgInvalidRevisionException, HgInvalidControlFileException { |
| 64 if (inspector == null) { | 65 if (inspector == null) { |
| 65 throw new IllegalArgumentException(); | 66 throw new IllegalArgumentException(); |
| 66 } | 67 } |
| 67 content.iterate(start, end, true, new RawCsetParser(inspector)); | 68 content.iterate(start, end, true, new RawCsetParser(inspector)); |
| 68 } | 69 } |
| 69 | 70 |
| 70 public List<RawChangeset> range(int start, int end) throws HgInvalidRevisionException { | 71 public List<RawChangeset> range(int start, int end) throws HgInvalidRevisionException, HgInvalidControlFileException { |
| 71 final RawCsetCollector c = new RawCsetCollector(end - start + 1); | 72 final RawCsetCollector c = new RawCsetCollector(end - start + 1); |
| 72 range(start, end, c); | 73 range(start, end, c); |
| 73 return c.result; | 74 return c.result; |
| 74 } | 75 } |
| 75 | 76 |
| 77 * Access individual revisions. Note, regardless of supplied revision order, inspector gets | 78 * Access individual revisions. Note, regardless of supplied revision order, inspector gets |
| 78 * changesets strictly in the order they are in the changelog. | 79 * changesets strictly in the order they are in the changelog. |
| 79 * @param inspector callback to get changesets | 80 * @param inspector callback to get changesets |
| 80 * @param revisions revisions to read, unrestricted ordering. | 81 * @param revisions revisions to read, unrestricted ordering. |
| 81 */ | 82 */ |
| 82 public void range(final HgChangelog.Inspector inspector, final int... revisions) throws HgInvalidRevisionException { | 83 public void range(final HgChangelog.Inspector inspector, final int... revisions) throws HgInvalidRevisionException, HgInvalidControlFileException { |
| 83 Arrays.sort(revisions); | 84 Arrays.sort(revisions); |
| 84 rangeInternal(inspector, revisions); | 85 rangeInternal(inspector, revisions); |
| 85 } | 86 } |
| 86 | 87 |
| 87 /** | 88 /** |
| 88 * Friends-only version of {@link #range(Inspector, int...)}, when callers know array is sorted | 89 * Friends-only version of {@link #range(Inspector, int...)}, when callers know array is sorted |
| 89 */ | 90 */ |
| 90 /*package-local*/ void rangeInternal(HgChangelog.Inspector inspector, int[] sortedRevisions) throws HgInvalidRevisionException { | 91 /*package-local*/ void rangeInternal(HgChangelog.Inspector inspector, int[] sortedRevisions) throws HgInvalidRevisionException, HgInvalidControlFileException { |
| 91 if (sortedRevisions == null || sortedRevisions.length == 0) { | 92 if (sortedRevisions == null || sortedRevisions.length == 0) { |
| 92 return; | 93 return; |
| 93 } | 94 } |
| 94 if (inspector == null) { | 95 if (inspector == null) { |
| 95 throw new IllegalArgumentException(); | 96 throw new IllegalArgumentException(); |
| 236 } catch (CloneNotSupportedException ex) { | 237 } catch (CloneNotSupportedException ex) { |
| 237 throw new InternalError(ex.toString()); | 238 throw new InternalError(ex.toString()); |
| 238 } | 239 } |
| 239 } | 240 } |
| 240 | 241 |
| 241 /*package*/ static RawChangeset parse(DataAccess da) throws IOException { | 242 /*package*/ static RawChangeset parse(DataAccess da) throws IOException, HgBadArgumentException { |
| 242 byte[] data = da.byteArray(); | 243 byte[] data = da.byteArray(); |
| 243 RawChangeset rv = new RawChangeset(); | 244 RawChangeset rv = new RawChangeset(); |
| 244 rv.init(data, 0, data.length, null); | 245 rv.init(data, 0, data.length, null); |
| 245 return rv; | 246 return rv; |
| 246 } | 247 } |
| 247 | 248 |
| 248 // @param usersPool - it's likely user names get repeated again and again throughout repository. can be null | 249 // @param usersPool - it's likely user names get repeated again and again throughout repository. can be null |
| 249 // FIXME throws "Error reading changeset data" | 250 // FIXME replace HgBadArgumentException with HgInvalidDataFormatException or HgInvalidControlFileException |
| 250 /* package-local */void init(byte[] data, int offset, int length, Pool<String> usersPool) { | 251 /* package-local */void init(byte[] data, int offset, int length, Pool<String> usersPool) throws HgBadArgumentException { |
| 251 final int bufferEndIndex = offset + length; | 252 final int bufferEndIndex = offset + length; |
| 252 final byte lineBreak = (byte) '\n'; | 253 final byte lineBreak = (byte) '\n'; |
| 253 int breakIndex1 = indexOf(data, lineBreak, offset, bufferEndIndex); | 254 int breakIndex1 = indexOf(data, lineBreak, offset, bufferEndIndex); |
| 254 if (breakIndex1 == -1) { | 255 if (breakIndex1 == -1) { |
| 255 throw new IllegalArgumentException("Bad Changeset data"); | 256 throw new HgBadArgumentException("Bad Changeset data", null); |
| 256 } | 257 } |
| 257 Nodeid _nodeid = Nodeid.fromAscii(data, 0, breakIndex1); | 258 Nodeid _nodeid = Nodeid.fromAscii(data, 0, breakIndex1); |
| 258 int breakIndex2 = indexOf(data, lineBreak, breakIndex1 + 1, bufferEndIndex); | 259 int breakIndex2 = indexOf(data, lineBreak, breakIndex1 + 1, bufferEndIndex); |
| 259 if (breakIndex2 == -1) { | 260 if (breakIndex2 == -1) { |
| 260 throw new IllegalArgumentException("Bad Changeset data"); | 261 throw new HgBadArgumentException("Bad Changeset data", null); |
| 261 } | 262 } |
| 262 String _user = new String(data, breakIndex1 + 1, breakIndex2 - breakIndex1 - 1); | 263 String _user = new String(data, breakIndex1 + 1, breakIndex2 - breakIndex1 - 1); |
| 263 if (usersPool != null) { | 264 if (usersPool != null) { |
| 264 _user = usersPool.unify(_user); | 265 _user = usersPool.unify(_user); |
| 265 } | 266 } |
| 266 int breakIndex3 = indexOf(data, lineBreak, breakIndex2 + 1, bufferEndIndex); | 267 int breakIndex3 = indexOf(data, lineBreak, breakIndex2 + 1, bufferEndIndex); |
| 267 if (breakIndex3 == -1) { | 268 if (breakIndex3 == -1) { |
| 268 throw new IllegalArgumentException("Bad Changeset data"); | 269 throw new HgBadArgumentException("Bad Changeset data", null); |
| 269 } | 270 } |
| 270 String _timeString = new String(data, breakIndex2 + 1, breakIndex3 - breakIndex2 - 1); | 271 String _timeString = new String(data, breakIndex2 + 1, breakIndex3 - breakIndex2 - 1); |
| 271 int space1 = _timeString.indexOf(' '); | 272 int space1 = _timeString.indexOf(' '); |
| 272 if (space1 == -1) { | 273 if (space1 == -1) { |
| 273 throw new IllegalArgumentException("Bad Changeset data"); | 274 throw new HgBadArgumentException(String.format("Bad Changeset data: %s in [%d..%d]", "time string", breakIndex2+1, breakIndex3), null); |
| 274 } | 275 } |
| 275 int space2 = _timeString.indexOf(' ', space1 + 1); | 276 int space2 = _timeString.indexOf(' ', space1 + 1); |
| 276 if (space2 == -1) { | 277 if (space2 == -1) { |
| 277 space2 = _timeString.length(); | 278 space2 = _timeString.length(); |
| 278 } | 279 } |
| 314 } else { | 315 } else { |
| 315 breakIndex4 = indexOf(data, lineBreak, lastStart, bufferEndIndex); | 316 breakIndex4 = indexOf(data, lineBreak, lastStart, bufferEndIndex); |
| 316 } | 317 } |
| 317 } | 318 } |
| 318 if (breakIndex4 == -1 || breakIndex4 >= bufferEndIndex) { | 319 if (breakIndex4 == -1 || breakIndex4 >= bufferEndIndex) { |
| 319 throw new IllegalArgumentException("Bad Changeset data"); | 320 throw new HgBadArgumentException("Bad Changeset data", null); |
| 320 } | 321 } |
| 321 } else { | 322 } else { |
| 322 breakIndex4--; | 323 breakIndex4--; |
| 323 } | 324 } |
| 324 String _comment; | 325 String _comment; |
| 325 try { | 326 try { |
| 326 _comment = new String(data, breakIndex4 + 2, bufferEndIndex - breakIndex4 - 2, "UTF-8"); | 327 _comment = new String(data, breakIndex4 + 2, bufferEndIndex - breakIndex4 - 2, "UTF-8"); |
| 327 // FIXME respect ui.fallbackencoding and try to decode if set | 328 // FIXME respect ui.fallbackencoding and try to decode if set |
| 328 } catch (UnsupportedEncodingException ex) { | 329 } catch (UnsupportedEncodingException ex) { |
| 329 _comment = ""; | 330 _comment = ""; |
| 330 throw new IllegalStateException("Could hardly happen"); | 331 // Could hardly happen |
| 332 throw new HgBadArgumentException("Bad Changeset data", ex); | |
| 331 } | 333 } |
| 332 // change this instance at once, don't leave it partially changes in case of error | 334 // change this instance at once, don't leave it partially changes in case of error |
| 333 this.manifest = _nodeid; | 335 this.manifest = _nodeid; |
| 334 this.user = _user; | 336 this.user = _user; |
| 335 this.time = _time; | 337 this.time = _time; |
| 382 inspector = delegate; | 384 inspector = delegate; |
| 383 usersPool = new Pool<String>(); | 385 usersPool = new Pool<String>(); |
| 384 progressHelper = ProgressSupport.Factory.get(delegate); | 386 progressHelper = ProgressSupport.Factory.get(delegate); |
| 385 } | 387 } |
| 386 | 388 |
| 387 public void next(int revisionNumber, int actualLen, int baseRevision, int linkRevision, int parent1Revision, int parent2Revision, byte[] nodeid, DataAccess da) { | 389 public void next(int revisionNumber, int actualLen, int baseRevision, int linkRevision, int parent1Revision, int parent2Revision, byte[] nodeid, DataAccess da) throws HgException { |
| 388 try { | 390 try { |
| 389 byte[] data = da.byteArray(); | 391 byte[] data = da.byteArray(); |
| 390 cset.init(data, 0, data.length, usersPool); | 392 cset.init(data, 0, data.length, usersPool); |
| 391 // XXX there's no guarantee for Changeset.Callback that distinct instance comes each time, consider instance reuse | 393 // XXX there's no guarantee for Changeset.Callback that distinct instance comes each time, consider instance reuse |
| 392 inspector.next(revisionNumber, Nodeid.fromBinary(nodeid, 0), cset); | 394 inspector.next(revisionNumber, Nodeid.fromBinary(nodeid, 0), cset); |
| 393 progressHelper.worked(1); | 395 progressHelper.worked(1); |
| 394 } catch (Exception ex) { | 396 } catch (IOException ex) { |
| 395 throw new HgBadStateException(ex); // FIXME exception handling | 397 throw new HgException(ex); // XXX need better exception, perhaps smth like HgChangelogException (extends HgInvalidControlFileException) |
| 396 } | 398 } |
| 397 if (iterateControl != null) { | 399 if (iterateControl != null) { |
| 398 iterateControl.checkCancelled(); | 400 iterateControl.checkCancelled(); |
| 399 } | 401 } |
| 400 } | 402 } |
