changeset 36:205f9b59b400

Strip parsing logic out from console frontend
author Artem Tikhomirov <tikhomirov.artem@gmail.com>
date Thu, 13 Jan 2011 23:31:39 +0100
parents 6061aa826a9e
children e45e75e22523
files src/com/tmate/hgkit/console/Bundle.java src/com/tmate/hgkit/ll/HgBundle.java src/com/tmate/hgkit/ll/RevlogStream.java
diffstat 3 files changed, 145 insertions(+), 61 deletions(-) [+]
line wrap: on
line diff
--- a/src/com/tmate/hgkit/console/Bundle.java	Thu Jan 13 20:02:21 2011 +0100
+++ b/src/com/tmate/hgkit/console/Bundle.java	Thu Jan 13 23:31:39 2011 +0100
@@ -4,14 +4,11 @@
 package com.tmate.hgkit.console;
 
 import java.io.File;
-import java.util.LinkedList;
 
-import com.tmate.hgkit.fs.DataAccess;
 import com.tmate.hgkit.fs.DataAccessProvider;
-import com.tmate.hgkit.ll.Nodeid;
+import com.tmate.hgkit.ll.HgBundle;
 
 /**
- * @see http://mercurial.selenic.com/wiki/BundleFormat
  *
  * @author artem
  */
@@ -20,49 +17,7 @@
 	public static void main(String[] args) throws Exception {
 		File bundleFile = new File("/temp/hg/hg-bundle-a78c980749e3.tmp");
 		DataAccessProvider dap = new DataAccessProvider();
-		DataAccess da = dap.create(bundleFile);
-		try {
-			LinkedList<String> names = new LinkedList<String>();
-			if (!da.isEmpty()) {
-				System.out.println("Changelog group");
-				readGroup(da);
-				System.out.println("Manifest group");
-				readGroup(da);
-				while (!da.isEmpty()) {
-					int fnameLen = da.readInt();
-					if (fnameLen <= 4) {
-						break; // null chunk, the last one.
-					}
-					byte[] fname = new byte[fnameLen - 4];
-					da.readBytes(fname, 0, fname.length);
-					names.add(new String(fname));
-					System.out.println(names.getLast());
-					readGroup(da);
-				}
-			}
-			System.out.println(names.size());
-			for (String s : names) {
-				System.out.println(s);
-			}
-		} finally {
-			da.done();
-		}
-	}
-
-	private static void readGroup(DataAccess da) throws Exception {
-		int len = da.readInt();
-		while (len > 4 && !da.isEmpty()) {
-			byte[] nb = new byte[80];
-			da.readBytes(nb, 0, 80);
-			Nodeid node = Nodeid.fromBinary(nb, 0);
-			Nodeid p1 = Nodeid.fromBinary(nb, 20);
-			Nodeid p2 = Nodeid.fromBinary(nb, 40);
-			Nodeid cs = Nodeid.fromBinary(nb, 60);
-			byte[] data = new byte[len-84];
-			da.readBytes(data, 0, data.length);
-			System.out.printf("%6d %s %s %s %s\n", len, node, p1, p2, cs);
-			System.out.println(new String(data));
-			len = da.isEmpty() ? 0 : da.readInt();
-		}
+		HgBundle hgBundle = new HgBundle(dap, bundleFile);
+		hgBundle.read();
 	}
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/com/tmate/hgkit/ll/HgBundle.java	Thu Jan 13 23:31:39 2011 +0100
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2011 Artem Tikhomirov 
+ */
+package com.tmate.hgkit.ll;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.LinkedList;
+import java.util.List;
+
+import com.tmate.hgkit.fs.DataAccess;
+import com.tmate.hgkit.fs.DataAccessProvider;
+
+/**
+ * @see http://mercurial.selenic.com/wiki/BundleFormat
+ *
+ * @author artem
+ */
+public class HgBundle {
+
+	private final File bundleFile;
+	private final DataAccessProvider accessProvider;
+
+	public HgBundle(DataAccessProvider dap, File bundle) {
+		accessProvider = dap;
+		bundleFile = bundle;
+	}
+
+	public void read() throws IOException {
+		DataAccess da = accessProvider.create(bundleFile);
+		try {
+			LinkedList<String> names = new LinkedList<String>();
+			if (!da.isEmpty()) {
+				System.out.println("Changelog group");
+				List<GroupElement> changelogGroup = readGroup(da);
+				for (GroupElement ge : changelogGroup) {
+					System.out.printf("  %s %s %s %s; patches:%d\n", ge.node(), ge.firstParent(), ge.secondParent(), ge.cs(), ge.patches.size());
+				}
+				System.out.println("Manifest group");
+				List<GroupElement> manifestGroup = readGroup(da);
+				for (GroupElement ge : manifestGroup) {
+					System.out.printf("  %s %s %s %s; patches:%d\n", ge.node(), ge.firstParent(), ge.secondParent(), ge.cs(), ge.patches.size());
+				}
+				while (!da.isEmpty()) {
+					int fnameLen = da.readInt();
+					if (fnameLen <= 4) {
+						break; // null chunk, the last one.
+					}
+					byte[] fname = new byte[fnameLen - 4];
+					da.readBytes(fname, 0, fname.length);
+					names.add(new String(fname));
+					List<GroupElement> fileGroup = readGroup(da);
+					System.out.println(names.getLast());
+					for (GroupElement ge : fileGroup) {
+						System.out.printf("  %s %s %s %s; patches:%d\n", ge.node(), ge.firstParent(), ge.secondParent(), ge.cs(), ge.patches.size());
+					}
+				}
+			}
+			System.out.println(names.size());
+			for (String s : names) {
+				System.out.println(s);
+			}
+		} finally {
+			da.done();
+		}
+	}
+
+	private static List<GroupElement> readGroup(DataAccess da) throws IOException {
+		int len = da.readInt();
+		LinkedList<GroupElement> rv = new LinkedList<HgBundle.GroupElement>();
+		while (len > 4 && !da.isEmpty()) {
+			byte[] nb = new byte[80];
+			da.readBytes(nb, 0, 80);
+			int dataLength = len-84;
+			LinkedList<RevlogStream.PatchRecord> patches = new LinkedList<RevlogStream.PatchRecord>();
+			while (dataLength > 0) {
+				RevlogStream.PatchRecord pr = RevlogStream.PatchRecord.read(da);
+				patches.add(pr);
+				dataLength -= pr.len + 12;
+			}
+			rv.add(new GroupElement(nb, patches));
+			len = da.isEmpty() ? 0 : da.readInt();
+		}
+		return rv;
+	}
+
+	static class GroupElement {
+		private byte[] header; // byte[80] takes 120 bytes, 4 Nodeids - 192
+		private List<RevlogStream.PatchRecord> patches;
+		
+		GroupElement(byte[] fourNodeids, List<RevlogStream.PatchRecord> patchList) {
+			assert fourNodeids != null && fourNodeids.length == 80;
+			// patchList.size() > 0
+			header = fourNodeids;
+			patches = patchList;
+		}
+		public Nodeid node() {
+			return Nodeid.fromBinary(header, 0);
+		}
+		public Nodeid firstParent() {
+			return Nodeid.fromBinary(header, 20);
+		}
+		public Nodeid secondParent() {
+			return Nodeid.fromBinary(header, 40);
+		}
+		public Nodeid cs() {
+			return Nodeid.fromBinary(header, 60);
+		}
+
+	}
+}
--- a/src/com/tmate/hgkit/ll/RevlogStream.java	Thu Jan 13 20:02:21 2011 +0100
+++ b/src/com/tmate/hgkit/ll/RevlogStream.java	Thu Jan 13 23:31:39 2011 +0100
@@ -190,12 +190,9 @@
 						LinkedList<PatchRecord> patches = new LinkedList<PatchRecord>();
 						int patchElementIndex = 0;
 						do {
-							final int x = patchElementIndex; // shorthand
-							int p1 =  ((data[x] & 0xFF)<< 24)    | ((data[x+1] & 0xFF) << 16) | ((data[x+2] & 0xFF) << 8)  | (data[x+3] & 0xFF);
-							int p2 =  ((data[x+4] & 0xFF) << 24) | ((data[x+5] & 0xFF) << 16) | ((data[x+6] & 0xFF) << 8)  | (data[x+7] & 0xFF);
-							int len = ((data[x+8] & 0xFF) << 24) | ((data[x+9] & 0xFF) << 16) | ((data[x+10] & 0xFF) << 8) | (data[x+11] & 0xFF);
-							patchElementIndex += 12 + len;
-							patches.add(new PatchRecord(p1, p2, len, data, x+12));
+							PatchRecord pr = PatchRecord.read(data, patchElementIndex);
+							patches.add(pr);
+							patchElementIndex += 12 + pr.len;
 						} while (patchElementIndex < data.length);
 						//
 						byte[] baseRevContent = lastData;
@@ -305,16 +302,37 @@
 	}
 
 	// @see http://mercurial.selenic.com/wiki/BundleFormat, in Changelog group description
-	static class PatchRecord { // copy of struct frag from mpatch.c
+	/*package-local*/ static class PatchRecord { // copy of struct frag from mpatch.c
 		int start, end, len;
 		byte[] data;
 
-		public PatchRecord(int p1, int p2, int len, byte[] src, int srcOffset) {
-		start = p1;
-				end = p2;
-				this.len = len;
-				data = new byte[len];
-				System.arraycopy(src, srcOffset, data, 0, len);
+		// TODO consider PatchRecord that only records data position (absolute in data source), and acquires data as needed 
+		private PatchRecord(int p1, int p2, int length, byte[] src) {
+			start = p1;
+			end = p2;
+			len = length;
+			data = src;
 		}
+
+		/*package-local*/ static PatchRecord read(byte[] data, int offset) {
+			final int x = offset; // shorthand
+			int p1 =  ((data[x] & 0xFF)<< 24)    | ((data[x+1] & 0xFF) << 16) | ((data[x+2] & 0xFF) << 8)  | (data[x+3] & 0xFF);
+			int p2 =  ((data[x+4] & 0xFF) << 24) | ((data[x+5] & 0xFF) << 16) | ((data[x+6] & 0xFF) << 8)  | (data[x+7] & 0xFF);
+			int len = ((data[x+8] & 0xFF) << 24) | ((data[x+9] & 0xFF) << 16) | ((data[x+10] & 0xFF) << 8) | (data[x+11] & 0xFF);
+			byte[] dataCopy = new byte[len];
+			System.arraycopy(data, x+12, dataCopy, 0, len);
+			return new PatchRecord(p1, p2, len, dataCopy);
+		}
+
+		/*package-local*/ static PatchRecord read(DataAccess da) throws IOException {
+			int p1 = da.readInt();
+			int p2 = da.readInt();
+			int len = da.readInt();
+			byte[] src = new byte[len];
+			da.readBytes(src, 0, len);
+			return new PatchRecord(p1, p2, len, src);
+		}
+		
+		
 	}
 }