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;