changeset 41:858d1b2458cb

Check integrity for bundle changelog. Sort nodeids when calculating hash
author Artem Tikhomirov <tikhomirov.artem@gmail.com>
date Fri, 14 Jan 2011 04:14:08 +0100
parents 21e26da142fa
children 92c3d0920d58
files design.txt src/com/tmate/hgkit/ll/DigestHelper.java src/com/tmate/hgkit/ll/HgBundle.java src/com/tmate/hgkit/ll/Nodeid.java
diffstat 4 files changed, 28 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/design.txt	Fri Jan 14 03:37:06 2011 +0100
+++ b/design.txt	Fri Jan 14 04:14:08 2011 +0100
@@ -37,6 +37,9 @@
 Changeset to get index (local revision number)
 RevisionWalker (on manifest) and WorkingCopyWalker (io.File) talking to ? and/or dirstate 
 RevlogStream - Inflater. Perhaps, InflaterStream instead?
+Implement use of fncache (use names from it - perhaps, would help for Mac issues Alex mentioned) along with 'digest'-ing long file names
+
+ 
  
 Status operation from GUI - guess, usually on a file/subfolder, hence API should allow for starting path (unlike cmdline, seems useless to implement include/exclide patterns - GUI users hardly enter them, ever)
 
--- a/src/com/tmate/hgkit/ll/DigestHelper.java	Fri Jan 14 03:37:06 2011 +0100
+++ b/src/com/tmate/hgkit/ll/DigestHelper.java	Fri Jan 14 04:14:08 2011 +0100
@@ -9,6 +9,7 @@
 import java.security.NoSuchAlgorithmException;
 
 /**
+ * TODO sha1_binary to give array for Nodeid.equalsTo 
  *
  * @author artem
  */
@@ -30,16 +31,27 @@
 		return sha1;
 	}
 
-	// XXX perhaps, digest functions should throw an exception, as it's caller responsibility to deal with eof, etc
+
+	public String sha1(Nodeid nodeid1, Nodeid nodeid2, byte[] data) {
+		return sha1(nodeid1.cloneData(), nodeid2.cloneData(), data);
+	}
+
+	//  sha1_digest(min(p1,p2) ++ max(p1,p2) ++ final_text)
 	public String sha1(byte[] nodeidParent1, byte[] nodeidParent2, byte[] data) {
 		MessageDigest alg = getSHA1();
-		alg.update(nodeidParent1);
-		alg.update(nodeidParent2);
+		if ((nodeidParent1[0] & 0x00FF) < (nodeidParent2[0] & 0x00FF)) { 
+			alg.update(nodeidParent1);
+			alg.update(nodeidParent2);
+		} else {
+			alg.update(nodeidParent2);
+			alg.update(nodeidParent1);
+		}
 		byte[] digest = alg.digest(data);
 		assert digest.length == 20;
 		return toHexString(digest, 0, 20);
 	}
 
+	// XXX perhaps, digest functions should throw an exception, as it's caller responsibility to deal with eof, etc
 	public byte[] sha1(InputStream is /*ByteBuffer*/) throws IOException {
 		MessageDigest alg = getSHA1();
 		byte[] buf = new byte[1024];
--- a/src/com/tmate/hgkit/ll/HgBundle.java	Fri Jan 14 03:37:06 2011 +0100
+++ b/src/com/tmate/hgkit/ll/HgBundle.java	Fri Jan 14 04:14:08 2011 +0100
@@ -28,6 +28,7 @@
 
 	public void changes(HgRepository hgRepo) throws IOException {
 		DataAccess da = accessProvider.create(bundleFile);
+		DigestHelper dh = new DigestHelper();
 		try {
 			List<GroupElement> changelogGroup = readGroup(da);
 			if (changelogGroup.isEmpty()) {
@@ -46,6 +47,9 @@
 			for (GroupElement ge : changelogGroup) {
 				int resultLen = 10000; // XXX calculate based on baseRevContent.length and ge.patches
 				byte[] csetContent = RevlogStream.apply(baseRevContent, resultLen, ge.patches);
+				// wiki suggests sha1_digest(min(p1,p2) ++ max(p1,p2) ++ final_text),
+				String digest = dh.sha1(ge.firstParent(), ge.secondParent(), csetContent); // XXX ge may give me access to byte[] content of nodeid directly, perhaps, I don't need DH to be friend of Nodeid?
+				System.out.println("Node: " + ge.node() + ", digest: " + digest);
 				Changeset cs = Changeset.parse(csetContent, 0, csetContent.length);
 				cs.dump();
 				baseRevContent = csetContent;
--- a/src/com/tmate/hgkit/ll/Nodeid.java	Fri Jan 14 03:37:06 2011 +0100
+++ b/src/com/tmate/hgkit/ll/Nodeid.java	Fri Jan 14 04:14:08 2011 +0100
@@ -75,6 +75,12 @@
 		return true;
 	}
 
+	// primary purpose is to give DigestHelper access to internal structure. Despite it's friends-only (package visibility), it's still makes sense to 
+	// return a copy, to avoid any accidental modification (same reason field is not made visible, nor any callback, e.g. Output.write(byte[]) was introduced)
+	/*package-local*/byte[] cloneData() {
+		return binaryData.clone();
+	}
+
 	// primary difference with cons is handling of NULL id (this method returns constant)
 	// always makes a copy of an array passed
 	public static Nodeid fromBinary(byte[] binaryRepresentation, int offset) {