Mercurial > jhg
comparison src/org/tmatesoft/hg/repo/HgDataFile.java @ 367:2fadf8695f8a
Use 'revision index' instead of the vague 'local revision number' concept in the API
| author | Artem Tikhomirov <tikhomirov.artem@gmail.com> |
|---|---|
| date | Fri, 16 Dec 2011 15:37:27 +0100 |
| parents | 189dc6dc1c3e |
| children | 8107b95f4280 |
comparison
equal
deleted
inserted
replaced
| 366:189dc6dc1c3e | 367:2fadf8695f8a |
|---|---|
| 14 * the terms of a license other than GNU General Public License | 14 * the terms of a license other than GNU General Public License |
| 15 * contact TMate Software at support@hg4j.com | 15 * contact TMate Software at support@hg4j.com |
| 16 */ | 16 */ |
| 17 package org.tmatesoft.hg.repo; | 17 package org.tmatesoft.hg.repo; |
| 18 | 18 |
| 19 import static org.tmatesoft.hg.repo.HgInternals.wrongLocalRevision; | 19 import static org.tmatesoft.hg.repo.HgInternals.wrongRevisionIndex; |
| 20 import static org.tmatesoft.hg.repo.HgRepository.*; | 20 import static org.tmatesoft.hg.repo.HgRepository.*; |
| 21 | 21 |
| 22 import java.io.ByteArrayOutputStream; | 22 import java.io.ByteArrayOutputStream; |
| 23 import java.io.File; | 23 import java.io.File; |
| 24 import java.io.FileInputStream; | 24 import java.io.FileInputStream; |
| 85 public Path getPath() { | 85 public Path getPath() { |
| 86 return path; // hgRepo.backresolve(this) -> name? In this case, what about hashed long names? | 86 return path; // hgRepo.backresolve(this) -> name? In this case, what about hashed long names? |
| 87 } | 87 } |
| 88 | 88 |
| 89 /** | 89 /** |
| 90 * Handy shorthand for {@link #length(int) length(getLocalRevision(nodeid))} | 90 * Handy shorthand for {@link #length(int) length(getRevisionIndex(nodeid))} |
| 91 * | 91 * |
| 92 * @param nodeid revision of the file | 92 * @param nodeid revision of the file |
| 93 * | 93 * |
| 94 * @return size of the file content at the given revision | 94 * @return size of the file content at the given revision |
| 95 * @throws HgInvalidRevisionException if supplied argument doesn't represent revision index in this revlog | 95 * @throws HgInvalidRevisionException if supplied argument doesn't represent revision index in this revlog |
| 96 * @throws HgDataStreamException if attempt to access file metadata failed | 96 * @throws HgDataStreamException if attempt to access file metadata failed |
| 97 * @throws HgInvalidControlFileException if access to revlog index/data entry failed | 97 * @throws HgInvalidControlFileException if access to revlog index/data entry failed |
| 98 */ | 98 */ |
| 99 public int length(Nodeid nodeid) throws HgDataStreamException, HgInvalidControlFileException, HgInvalidRevisionException { | 99 public int length(Nodeid nodeid) throws HgDataStreamException, HgInvalidControlFileException, HgInvalidRevisionException { |
| 100 return length(getLocalRevision(nodeid)); | 100 return length(getRevisionIndex(nodeid)); |
| 101 } | 101 } |
| 102 | 102 |
| 103 /** | 103 /** |
| 104 * @param fileRevisionIndex local revision index, non-negative. From predefined constants, only {@link HgRepository#TIP} makes sense. | |
| 104 * @return size of the file content at the revision identified by local revision number. | 105 * @return size of the file content at the revision identified by local revision number. |
| 105 * @throws HgInvalidRevisionException if supplied argument doesn't represent revision index in this revlog | 106 * @throws HgInvalidRevisionException if supplied argument doesn't represent revision index in this revlog |
| 106 * @throws HgDataStreamException if attempt to access file metadata failed | 107 * @throws HgDataStreamException if attempt to access file metadata failed |
| 107 * @throws HgInvalidControlFileException if access to revlog index/data entry failed | 108 * @throws HgInvalidControlFileException if access to revlog index/data entry failed |
| 108 */ | 109 */ |
| 109 public int length(int localRev) throws HgDataStreamException, HgInvalidControlFileException, HgInvalidRevisionException { | 110 public int length(int fileRevisionIndex) throws HgDataStreamException, HgInvalidControlFileException, HgInvalidRevisionException { |
| 110 if (metadata == null || !metadata.checked(localRev)) { | 111 // TODO support WORKING_COPY constant |
| 111 checkAndRecordMetadata(localRev); | 112 if (metadata == null || !metadata.checked(fileRevisionIndex)) { |
| 112 } | 113 checkAndRecordMetadata(fileRevisionIndex); |
| 113 final int dataLen = content.dataLength(localRev); | 114 } |
| 114 if (metadata.known(localRev)) { | 115 final int dataLen = content.dataLength(fileRevisionIndex); |
| 115 return dataLen - metadata.dataOffset(localRev); | 116 if (metadata.known(fileRevisionIndex)) { |
| 117 return dataLen - metadata.dataOffset(fileRevisionIndex); | |
| 116 } | 118 } |
| 117 return dataLen; | 119 return dataLen; |
| 118 } | 120 } |
| 119 | 121 |
| 120 /** | 122 /** |
| 196 } else { | 198 } else { |
| 197 content(revision, new FilterByteChannel(sink, getRepo().getFiltersFromRepoToWorkingDir(getPath()))); | 199 content(revision, new FilterByteChannel(sink, getRepo().getFiltersFromRepoToWorkingDir(getPath()))); |
| 198 } | 200 } |
| 199 } | 201 } |
| 200 | 202 |
| 201 // for data files need to check heading of the file content for possible metadata | 203 /** |
| 202 // @see http://mercurial.selenic.com/wiki/FileFormats#data.2BAC8- | 204 * |
| 203 public void content(int revision, ByteChannel sink) throws HgDataStreamException, HgInvalidControlFileException, CancelledException, HgInvalidRevisionException { | 205 * @param fileRevisionIndex local revision index, non-negative. From predefined constants, {@link HgRepository#TIP} and {@link HgRepository#WORKING_COPY} make sense. |
| 204 if (revision == TIP) { | 206 * @param sink |
| 205 revision = getLastRevision(); | 207 * @throws HgDataStreamException FIXME |
| 206 } | 208 * @throws HgInvalidControlFileException |
| 207 if (revision == WORKING_COPY) { | 209 * @throws CancelledException |
| 210 * @throws HgInvalidRevisionException | |
| 211 */ | |
| 212 public void content(int fileRevisionIndex, ByteChannel sink) throws HgDataStreamException, HgInvalidControlFileException, CancelledException, HgInvalidRevisionException { | |
| 213 // for data files need to check heading of the file content for possible metadata | |
| 214 // @see http://mercurial.selenic.com/wiki/FileFormats#data.2BAC8- | |
| 215 if (fileRevisionIndex == TIP) { | |
| 216 fileRevisionIndex = getLastRevision(); | |
| 217 } | |
| 218 if (fileRevisionIndex == WORKING_COPY) { | |
| 208 // sink is supposed to come into workingCopy without filters | 219 // sink is supposed to come into workingCopy without filters |
| 209 // thus we shall not get here (into #content) from #contentWithFilters(WC) | 220 // thus we shall not get here (into #content) from #contentWithFilters(WC) |
| 210 workingCopy(sink); | 221 workingCopy(sink); |
| 211 return; | 222 return; |
| 212 } | 223 } |
| 213 if (wrongLocalRevision(revision) || revision == BAD_REVISION) { | 224 if (wrongRevisionIndex(fileRevisionIndex) || fileRevisionIndex == BAD_REVISION) { |
| 214 throw new HgInvalidRevisionException(revision); | 225 throw new HgInvalidRevisionException(fileRevisionIndex); |
| 215 } | 226 } |
| 216 if (sink == null) { | 227 if (sink == null) { |
| 217 throw new IllegalArgumentException(); | 228 throw new IllegalArgumentException(); |
| 218 } | 229 } |
| 219 if (metadata == null) { | 230 if (metadata == null) { |
| 220 metadata = new Metadata(); | 231 metadata = new Metadata(); |
| 221 } | 232 } |
| 222 ErrorHandlingInspector insp; | 233 ErrorHandlingInspector insp; |
| 223 if (metadata.none(revision)) { | 234 if (metadata.none(fileRevisionIndex)) { |
| 224 insp = new ContentPipe(sink, 0, getRepo().getContext().getLog()); | 235 insp = new ContentPipe(sink, 0, getRepo().getContext().getLog()); |
| 225 } else if (metadata.known(revision)) { | 236 } else if (metadata.known(fileRevisionIndex)) { |
| 226 insp = new ContentPipe(sink, metadata.dataOffset(revision), getRepo().getContext().getLog()); | 237 insp = new ContentPipe(sink, metadata.dataOffset(fileRevisionIndex), getRepo().getContext().getLog()); |
| 227 } else { | 238 } else { |
| 228 // do not know if there's metadata | 239 // do not know if there's metadata |
| 229 insp = new MetadataInspector(metadata, getPath(), new ContentPipe(sink, 0, getRepo().getContext().getLog())); | 240 insp = new MetadataInspector(metadata, getPath(), new ContentPipe(sink, 0, getRepo().getContext().getLog())); |
| 230 } | 241 } |
| 231 insp.checkCancelled(); | 242 insp.checkCancelled(); |
| 232 super.content.iterate(revision, revision, true, insp); | 243 super.content.iterate(fileRevisionIndex, fileRevisionIndex, true, insp); |
| 233 try { | 244 try { |
| 234 insp.checkFailed(); // XXX is there real need to throw IOException from ContentPipe? | 245 insp.checkFailed(); // XXX is there real need to throw IOException from ContentPipe? |
| 235 } catch (HgDataStreamException ex) { | 246 } catch (HgDataStreamException ex) { |
| 236 throw ex; | 247 throw ex; |
| 237 } catch (IOException ex) { | 248 } catch (IOException ex) { |
| 238 throw new HgDataStreamException(getPath(), ex).setRevisionNumber(revision); | 249 throw new HgDataStreamException(getPath(), ex).setRevisionIndex(fileRevisionIndex); |
| 239 } catch (HgException ex) { | 250 } catch (HgException ex) { |
| 240 // shall not happen, unless we changed ContentPipe or its subclass | 251 // shall not happen, unless we changed ContentPipe or its subclass |
| 241 throw new HgDataStreamException(getPath(), ex.getClass().getName(), ex); | 252 throw new HgDataStreamException(getPath(), ex.getClass().getName(), ex); |
| 242 } | 253 } |
| 243 } | 254 } |
| 398 } | 409 } |
| 399 changelog.rangeInternal(inspector, commitRevisions); | 410 changelog.rangeInternal(inspector, commitRevisions); |
| 400 } | 411 } |
| 401 | 412 |
| 402 /** | 413 /** |
| 403 * For a given local revision of the file, find out local revision in the changelog. | 414 * For a given revision of the file (identified with revision index), find out index of the corresponding changeset. |
| 404 * FIXME rename to getChangesetRevisionIndex() | |
| 405 * | 415 * |
| 406 * @return changeset revision index | 416 * @return changeset revision index |
| 407 * @throws HgInvalidRevisionException if supplied argument doesn't represent revision index in this revlog | 417 * @throws HgInvalidRevisionException if supplied argument doesn't represent revision index in this revlog |
| 408 * @throws HgInvalidControlFileException if access to revlog index/data entry failed | 418 * @throws HgInvalidControlFileException if access to revlog index/data entry failed |
| 409 */ | 419 */ |
| 420 public int getChangesetRevisionIndex(int revision) throws HgInvalidControlFileException, HgInvalidRevisionException { | |
| 421 return content.linkRevision(revision); | |
| 422 } | |
| 423 /** | |
| 424 * @deprecated use {@link #getChangesetRevisionIndex(int)} instead | |
| 425 */ | |
| 426 @Deprecated | |
| 410 public int getChangesetLocalRevision(int revision) throws HgInvalidControlFileException, HgInvalidRevisionException { | 427 public int getChangesetLocalRevision(int revision) throws HgInvalidControlFileException, HgInvalidRevisionException { |
| 411 return content.linkRevision(revision); | 428 return getChangesetRevisionIndex(revision); |
| 412 } | 429 } |
| 413 | 430 |
| 414 /** | 431 /** |
| 415 * Complements {@link #getChangesetLocalRevision(int)} to get changeset revision that corresponds to supplied file revision | 432 * Complements {@link #getChangesetRevisionIndex(int)} to get changeset revision that corresponds to supplied file revision |
| 416 * | 433 * |
| 417 * @param nid revision of the file | 434 * @param nid revision of the file |
| 418 * @return changeset revision | 435 * @return changeset revision |
| 419 * @throws HgInvalidRevisionException if supplied argument doesn't represent revision index in this revlog | 436 * @throws HgInvalidRevisionException if supplied argument doesn't represent revision index in this revlog |
| 420 * @throws HgInvalidControlFileException if access to revlog index/data entry failed | 437 * @throws HgInvalidControlFileException if access to revlog index/data entry failed |
| 421 */ | 438 */ |
| 422 public Nodeid getChangesetRevision(Nodeid nid) throws HgInvalidControlFileException, HgInvalidRevisionException { | 439 public Nodeid getChangesetRevision(Nodeid nid) throws HgInvalidControlFileException, HgInvalidRevisionException { |
| 423 int changelogRevision = getChangesetLocalRevision(getLocalRevision(nid)); | 440 int changelogRevision = getChangesetRevisionIndex(getRevisionIndex(nid)); |
| 424 return getRepo().getChangelog().getRevision(changelogRevision); | 441 return getRepo().getChangelog().getRevision(changelogRevision); |
| 425 } | 442 } |
| 426 | 443 |
| 427 /** | 444 /** |
| 428 * | 445 * |
| 603 delegate.next(revisionNumber, actualLen, baseRevision, linkRevision, parent1Revision, parent2Revision, nodeid, data); | 620 delegate.next(revisionNumber, actualLen, baseRevision, linkRevision, parent1Revision, parent2Revision, nodeid, data); |
| 604 } | 621 } |
| 605 } catch (IOException ex) { | 622 } catch (IOException ex) { |
| 606 recordFailure(ex); | 623 recordFailure(ex); |
| 607 } catch (HgDataStreamException ex) { | 624 } catch (HgDataStreamException ex) { |
| 608 recordFailure(ex.setRevisionNumber(revisionNumber)); | 625 recordFailure(ex.setRevisionIndex(revisionNumber)); |
| 609 } | 626 } |
| 610 } | 627 } |
| 611 | 628 |
| 612 private int parseMetadata(DataAccess data, final int daLength, ArrayList<MetadataEntry> _metadata) throws IOException, HgDataStreamException { | 629 private int parseMetadata(DataAccess data, final int daLength, ArrayList<MetadataEntry> _metadata) throws IOException, HgDataStreamException { |
| 613 int lastEntryStart = 2; | 630 int lastEntryStart = 2; |
