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