diff src/org/tmatesoft/hg/repo/HgDataFile.java @ 275:6d1804fe0ed7

Issue 10: Report file content length with respect of metadata. Respect dirstate parents for WC's status. Exceptions to keep useful attributes of the location
author Artem Tikhomirov <tikhomirov.artem@gmail.com>
date Thu, 25 Aug 2011 21:35:03 +0200
parents 2fb439375ddc
children 6355ecda1f08
line wrap: on
line diff
--- a/src/org/tmatesoft/hg/repo/HgDataFile.java	Thu Aug 25 03:57:39 2011 +0200
+++ b/src/org/tmatesoft/hg/repo/HgDataFile.java	Thu Aug 25 21:35:03 2011 +0200
@@ -79,8 +79,26 @@
 		return path; // hgRepo.backresolve(this) -> name? In this case, what about hashed long names?
 	}
 
-	public int length(Nodeid nodeid) {
-		return content.dataLength(getLocalRevision(nodeid));
+	/**
+	 * @return size of the file content at the given revision
+	 */
+	public int length(Nodeid nodeid) throws HgDataStreamException {
+		return length(getLocalRevision(nodeid));
+		
+	}
+	
+	/**
+	 * @return size of the file content at the revision identified by local revision number.
+	 */
+	public int length(int localRev) throws HgDataStreamException {
+		if (metadata == null || !metadata.checked(localRev)) {
+			checkAndRecordMetadata(localRev);
+		}
+		final int dataLen = content.dataLength(localRev);
+		if (metadata.known(localRev)) {
+			return dataLen - metadata.dataOffset(localRev);
+		}
+		return dataLen;
 	}
 
 	/**
@@ -258,27 +276,7 @@
 
 	public boolean isCopy() throws HgDataStreamException {
 		if (metadata == null || !metadata.checked(0)) {
-			// content() always initializes metadata.
-			// FIXME this is expensive way to find out metadata, distinct RevlogStream.Iterator would be better.
-			// Alternatively, may parameterize MetadataContentPipe to do prepare only.
-			// For reference, when throwing CancelledException, hg status -A --rev 3:80 takes 70 ms
-			// however, if we just consume buffer instead (buffer.position(buffer.limit()), same command takes ~320ms
-			// (compared to command-line counterpart of 190ms)
-			try {
-				content(0, new ByteChannel() { // No-op channel
-					public int write(ByteBuffer buffer) throws IOException, CancelledException {
-						// pretend we consumed whole buffer
-//						int rv = buffer.remaining();
-//						buffer.position(buffer.limit());
-//						return rv;
-						throw new CancelledException();
-					}
-				});
-			} catch (CancelledException ex) {
-				// it's ok, we did that
-			} catch (Exception ex) {
-				throw new HgDataStreamException(getPath(), "Can't initialize metadata", ex);
-			}
+			checkAndRecordMetadata(0);
 		}
 		if (!metadata.known(0)) {
 			return false;
@@ -308,6 +306,26 @@
 		sb.append(')');
 		return sb.toString();
 	}
+	
+	private void checkAndRecordMetadata(int localRev) throws HgDataStreamException {
+		// content() always initializes metadata.
+		// FIXME this is expensive way to find out metadata, distinct RevlogStream.Iterator would be better.
+		// Alternatively, may parameterize MetadataContentPipe to do prepare only.
+		// For reference, when throwing CancelledException, hg status -A --rev 3:80 takes 70 ms
+		// however, if we just consume buffer instead (buffer.position(buffer.limit()), same command takes ~320ms
+		// (compared to command-line counterpart of 190ms)
+		try {
+			content(localRev, new ByteChannel() { // No-op channel
+				public int write(ByteBuffer buffer) throws IOException, CancelledException {
+					throw new CancelledException();
+				}
+			});
+		} catch (CancelledException ex) {
+			// it's ok, we did that
+		} catch (Exception ex) {
+			throw new HgDataStreamException(getPath(), "Can't initialize metadata", ex).setRevisionNumber(localRev);
+		}
+	}
 
 	private static final class MetadataEntry {
 		private final String entry;