diff src/org/tmatesoft/hg/core/HgChangeset.java @ 195:c9b305df0b89

Optimization: use ParentWalker to get changeset's parents, if possible. Do not keep duplicating nodeids and strings in manifest revisions
author Artem Tikhomirov <tikhomirov.artem@gmail.com>
date Fri, 15 Apr 2011 05:17:44 +0200
parents ba2bf656f00f
children e2115da4cf6a
line wrap: on
line diff
--- a/src/org/tmatesoft/hg/core/HgChangeset.java	Fri Apr 15 03:35:08 2011 +0200
+++ b/src/org/tmatesoft/hg/core/HgChangeset.java	Fri Apr 15 05:17:44 2011 +0200
@@ -16,12 +16,15 @@
  */
 package org.tmatesoft.hg.core;
 
+import static org.tmatesoft.hg.core.Nodeid.NULL;
+
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 
 import org.tmatesoft.hg.core.HgLogCommand.FileRevision;
 import org.tmatesoft.hg.repo.HgChangelog.RawChangeset;
+import org.tmatesoft.hg.repo.HgChangelog;
 import org.tmatesoft.hg.repo.HgRepository;
 import org.tmatesoft.hg.repo.HgStatusCollector;
 import org.tmatesoft.hg.util.Path;
@@ -39,6 +42,8 @@
 	private final HgStatusCollector statusHelper;
 	private final Path.Source pathHelper;
 
+	private HgChangelog.ParentWalker parentHelper;
+
 	//
 	private RawChangeset changeset;
 	private Nodeid nodeid;
@@ -47,6 +52,7 @@
 	private List<FileRevision> modifiedFiles, addedFiles;
 	private List<Path> deletedFiles;
 	private int revNumber;
+	private byte[] parent1, parent2;
 
 	// XXX consider CommandContext with StatusCollector, PathPool etc. Commands optionally get CC through a cons or create new
 	// and pass it around
@@ -54,15 +60,26 @@
 		statusHelper = statusCollector;
 		pathHelper = pathFactory;
 	}
-	
-	/*package-local*/
-	void init(int localRevNumber, Nodeid nid, RawChangeset rawChangeset) {
+
+	/*package-local*/ void init(int localRevNumber, Nodeid nid, RawChangeset rawChangeset) {
 		revNumber = localRevNumber;
 		nodeid = nid;
 		changeset = rawChangeset;
 		modifiedFiles = addedFiles = null;
 		deletedFiles = null;
+		parent1 = parent2 = null;
+		// keep references to parentHelper, statusHelper and pathHelper
 	}
+
+	/*package-local*/ void setParentHelper(HgChangelog.ParentWalker pw) {
+		parentHelper = pw;
+		if (parentHelper != null) {
+			if (parentHelper.getRepo() != statusHelper.getRepo()) {
+				throw new IllegalArgumentException();
+			}
+		}
+	}
+
 	public int getRevision() {
 		return revNumber;
 	}
@@ -119,21 +136,33 @@
 	}
 
 	public boolean isMerge() {
-		return !Nodeid.NULL.equals(getSecondParentRevision());
+		// p1 == -1 and p2 != -1 is legitimate case
+		return !NULL.equals(getFirstParentRevision()) && !NULL.equals(getSecondParentRevision()); 
 	}
 	
 	public Nodeid getFirstParentRevision() {
-		// XXX may read once for both p1 and p2 
-		// or use ParentWalker to minimize reads even more.
-		byte[] p1 = new byte[20];
-		statusHelper.getRepo().getChangelog().parents(revNumber, new int[2], p1, null);
-		return Nodeid.fromBinary(p1, 0);
+		if (parentHelper != null) {
+			return parentHelper.safeFirstParent(nodeid);
+		}
+		// read once for both p1 and p2
+		if (parent1 == null) {
+			parent1 = new byte[20];
+			parent2 = new byte[20];
+			statusHelper.getRepo().getChangelog().parents(revNumber, new int[2], parent1, parent2);
+		}
+		return Nodeid.fromBinary(parent1, 0);
 	}
 	
 	public Nodeid getSecondParentRevision() {
-		byte[] p2 = new byte[20];
-		statusHelper.getRepo().getChangelog().parents(revNumber, new int[2], null, p2);
-		return Nodeid.fromBinary(p2, 0);
+		if (parentHelper != null) {
+			return parentHelper.safeSecondParent(nodeid);
+		}
+		if (parent2 == null) {
+			parent1 = new byte[20];
+			parent2 = new byte[20];
+			statusHelper.getRepo().getChangelog().parents(revNumber, new int[2], parent1, parent2);
+		}
+		return Nodeid.fromBinary(parent2, 0);
 	}
 
 	@Override