changeset 59:b771e94a4f7c

Introduce Internals to keep LocalHgRepo casts and alike in a single place. WCSC optionally to reuse SC data
author Artem Tikhomirov <tikhomirov.artem@gmail.com>
date Tue, 18 Jan 2011 00:08:15 +0100
parents 4cfc47bc14cc
children 613c936d74e4
files src/com/tmate/hgkit/console/Cat.java src/com/tmate/hgkit/console/Status.java src/com/tmate/hgkit/ll/HgDirstate.java src/com/tmate/hgkit/ll/Internals.java src/com/tmate/hgkit/ll/LocalHgRepo.java src/com/tmate/hgkit/ll/StatusCollector.java src/com/tmate/hgkit/ll/WorkingCopyStatusCollector.java
diffstat 7 files changed, 107 insertions(+), 39 deletions(-) [+]
line wrap: on
line diff
--- a/src/com/tmate/hgkit/console/Cat.java	Mon Jan 17 23:01:19 2011 +0100
+++ b/src/com/tmate/hgkit/console/Cat.java	Tue Jan 18 00:08:15 2011 +0100
@@ -6,9 +6,8 @@
 import com.tmate.hgkit.fs.RepositoryLookup;
 import com.tmate.hgkit.ll.DigestHelper;
 import com.tmate.hgkit.ll.HgDataFile;
-import com.tmate.hgkit.ll.HgIgnore;
 import com.tmate.hgkit.ll.HgRepository;
-import com.tmate.hgkit.ll.LocalHgRepo;
+import com.tmate.hgkit.ll.Internals;
 
 /**
  * @author artem
@@ -24,9 +23,11 @@
 			System.err.printf("Can't find repository in: %s\n", hgRepo.getLocation());
 			return;
 		}
-		HgIgnore ignore = ((LocalHgRepo) hgRepo).loadIgnore();
-		for (String s : new String[] {"design.txt", "src/com/tmate/hgkit/ll/Changelog.java", "src/Extras.java", "bin/com/tmate/hgkit/ll/Changelog.class"} ) {
-			System.out.println("Ignored " + s + ": " + ignore.isIgnored(s));
+		Internals debug = new Internals(hgRepo);
+		String[] toCheck = new String[] {"design.txt", "src/com/tmate/hgkit/ll/Changelog.java", "src/Extras.java", "bin/com/tmate/hgkit/ll/Changelog.class"};
+		boolean[] checkResult = debug.checkIgnored(toCheck);
+		for (int i = 0; i < toCheck.length; i++) {
+			System.out.println("Ignored " + toCheck[i] + ": " + checkResult[i]);
 		}
 		DigestHelper dh = new DigestHelper();
 		for (String fname : cmdLineOpts.files) {
--- a/src/com/tmate/hgkit/console/Status.java	Mon Jan 17 23:01:19 2011 +0100
+++ b/src/com/tmate/hgkit/console/Status.java	Tue Jan 18 00:08:15 2011 +0100
@@ -12,6 +12,7 @@
 import com.tmate.hgkit.fs.RepositoryLookup;
 import com.tmate.hgkit.ll.HgDataFile;
 import com.tmate.hgkit.ll.HgRepository;
+import com.tmate.hgkit.ll.Internals;
 import com.tmate.hgkit.ll.LocalHgRepo;
 import com.tmate.hgkit.ll.Nodeid;
 import com.tmate.hgkit.ll.StatusCollector;
@@ -32,7 +33,8 @@
 			return;
 		}
 		System.out.println(hgRepo.getLocation());
-		((LocalHgRepo) hgRepo).loadDirstate().dump();
+		Internals debug = new Internals(hgRepo);
+		debug.dumpDirstate();
 		final StatusDump dump = new StatusDump();
 		dump.showIgnored = false;
 		dump.showClean = false;
--- a/src/com/tmate/hgkit/ll/HgDirstate.java	Mon Jan 17 23:01:19 2011 +0100
+++ b/src/com/tmate/hgkit/ll/HgDirstate.java	Tue Jan 18 00:08:15 2011 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010 Artem Tikhomirov 
+ * Copyright (c) 2010, 2011 Artem Tikhomirov 
  */
 package com.tmate.hgkit.ll;
 
@@ -20,25 +20,30 @@
  */
 public class HgDirstate {
 
-	private final LocalHgRepo repo;
+	private final DataAccessProvider accessProvider;
 	private final File dirstateFile;
 	private Map<String, Record> normal;
 	private Map<String, Record> added;
 	private Map<String, Record> removed;
 	private Map<String, Record> merged;
 
-	public HgDirstate(LocalHgRepo hgRepo, File dirstate) {
-		this.repo = hgRepo;
-		this.dirstateFile = dirstate;
+	/*package-local*/ HgDirstate() {
+		// empty instance
+		accessProvider = null;
+		dirstateFile = null;
+	}
+
+	public HgDirstate(DataAccessProvider dap, File dirstate) {
+		accessProvider = dap;
+		dirstateFile = dirstate;
 	}
 
 	private void read() {
 		normal = added = removed = merged = Collections.<String, Record>emptyMap();
-		if (!dirstateFile.exists()) {
+		if (dirstateFile == null || !dirstateFile.exists()) {
 			return;
 		}
-		DataAccessProvider dap = repo.getDataAccess();
-		DataAccess da = dap.create(dirstateFile);
+		DataAccess da = accessProvider.create(dirstateFile);
 		if (da.isEmpty()) {
 			return;
 		}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/com/tmate/hgkit/ll/Internals.java	Tue Jan 18 00:08:15 2011 +0100
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2011 Artem Tikhomirov 
+ */
+package com.tmate.hgkit.ll;
+
+/**
+ * DO NOT USE THIS CLASS, INTENDED FOR TESTING PURPOSES.
+ * 
+ * Debug helper, to access otherwise restricted (package-local) methods
+ * 
+ * @author artem
+ */
+public class Internals {
+
+	private final HgRepository repo;
+
+	public Internals(HgRepository hgRepo) {
+		this.repo = hgRepo;
+	}
+
+	public void dumpDirstate() {
+		if (repo instanceof LocalHgRepo) {
+			((LocalHgRepo) repo).loadDirstate().dump();
+		}
+	}
+
+	public boolean[] checkIgnored(String... toCheck) {
+		if (repo instanceof LocalHgRepo) {
+			HgIgnore ignore = ((LocalHgRepo) repo).loadIgnore();
+			boolean[] rv = new boolean[toCheck.length];
+			for (int i = 0; i < toCheck.length; i++) {
+				rv[i] = ignore.isIgnored(toCheck[i]);
+			}
+			return rv;
+		}
+		return new boolean[0];
+	}
+}
--- a/src/com/tmate/hgkit/ll/LocalHgRepo.java	Mon Jan 17 23:01:19 2011 +0100
+++ b/src/com/tmate/hgkit/ll/LocalHgRepo.java	Tue Jan 18 00:08:15 2011 +0100
@@ -3,20 +3,14 @@
  */
 package com.tmate.hgkit.ll;
 
-import java.io.BufferedInputStream;
 import java.io.BufferedReader;
 import java.io.File;
-import java.io.FileFilter;
 import java.io.FileInputStream;
-import java.io.FilenameFilter;
 import java.io.IOException;
 import java.io.InputStreamReader;
 import java.lang.ref.SoftReference;
 import java.util.Arrays;
-import java.util.Collections;
 import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.Set;
 import java.util.TreeSet;
 
 import com.tmate.hgkit.fs.DataAccessProvider;
@@ -56,9 +50,8 @@
 	}
 	
 	// XXX package-local, unless there are cases when required from outside (guess, working dir/revision walkers may hide dirstate access and no public visibility needed)
-	public final HgDirstate loadDirstate() {
-		// XXX may cache in SoftReference if creation is expensive
-		return new HgDirstate(this, new File(repoDir, "dirstate"));
+	final HgDirstate loadDirstate() {
+		return new HgDirstate(getDataAccess(), new File(repoDir, "dirstate"));
 	}
 
 	// package-local, see comment for loadDirstate
--- a/src/com/tmate/hgkit/ll/StatusCollector.java	Mon Jan 17 23:01:19 2011 +0100
+++ b/src/com/tmate/hgkit/ll/StatusCollector.java	Tue Jan 18 00:08:15 2011 +0100
@@ -40,6 +40,10 @@
 		return i;
 	}
 	
+	/*package-local*/ ManifestRevisionInspector raw(int rev) {
+		return get(rev);
+	}
+	
 	// hg status --change <rev>
 	public void change(int rev, Inspector inspector) {
 		int[] parents = new int[2];
--- a/src/com/tmate/hgkit/ll/WorkingCopyStatusCollector.java	Mon Jan 17 23:01:19 2011 +0100
+++ b/src/com/tmate/hgkit/ll/WorkingCopyStatusCollector.java	Tue Jan 18 00:08:15 2011 +0100
@@ -23,22 +23,47 @@
 
 	private final HgRepository repo;
 	private final FileWalker repoWalker;
+	private HgDirstate dirstate;
+	private StatusCollector baseRevisionCollector;
 
 	public WorkingCopyStatusCollector(HgRepository hgRepo, FileWalker hgRepoWalker) {
 		this.repo = hgRepo;
 		this.repoWalker = hgRepoWalker;
 	}
+	
+	/**
+	 * Optionally, supply a collector instance that may cache (or have already cached) base revision
+	 * @param sc may be null
+	 */
+	public void setBseRevisionCollector(StatusCollector sc) {
+		baseRevisionCollector = sc;
+	}
+	
+	private HgDirstate getDirstate() {
+		if (dirstate == null) {
+			if (repo instanceof LocalHgRepo) {
+				dirstate = ((LocalHgRepo) repo).loadDirstate();
+			} else {
+				dirstate = new HgDirstate();
+			}
+		}
+		return dirstate;
+	}
 
+	// may be invoked few times
 	public void walk(int baseRevision, StatusCollector.Inspector inspector) {
 		final HgIgnore hgIgnore = ((LocalHgRepo) repo).loadIgnore(); // FIXME hack
-		final HgDirstate dirstate = ((LocalHgRepo) repo).loadDirstate(); // FIXME hack
-		TreeSet<String> knownEntries = dirstate.all();
+		TreeSet<String> knownEntries = getDirstate().all();
 		final boolean isTipBase = baseRevision == TIP || baseRevision == repo.getManifest().getRevisionCount();
 		StatusCollector.ManifestRevisionInspector collect = null;
 		Set<String> baseRevFiles = Collections.emptySet();
 		if (!isTipBase) {
-			collect = new StatusCollector.ManifestRevisionInspector(baseRevision, baseRevision);
-			repo.getManifest().walk(baseRevision, baseRevision, collect);
+			if (baseRevisionCollector != null) {
+				collect = baseRevisionCollector.raw(baseRevision);
+			} else {
+				collect = new StatusCollector.ManifestRevisionInspector(baseRevision, baseRevision);
+				repo.getManifest().walk(baseRevision, baseRevision, collect);
+			}
 			baseRevFiles = new TreeSet<String>(collect.files(baseRevision));
 		}
 		repoWalker.reset();
@@ -53,10 +78,10 @@
 				if (collect != null) { // need to check against base revision, not FS file
 					Nodeid nid1 = collect.nodeid(baseRevision, fname);
 					String flags = collect.flags(baseRevision, fname);
-					checkLocalStatusAgainstBaseRevision(baseRevFiles, nid1, flags, fname, f, dirstate, inspector);
+					checkLocalStatusAgainstBaseRevision(baseRevFiles, nid1, flags, fname, f, inspector);
 					baseRevFiles.remove(fname);
 				} else {
-					checkLocalStatusAgainstFile(fname, f, dirstate, inspector);
+					checkLocalStatusAgainstFile(fname, f, inspector);
 				}
 			} else {
 				inspector.unknown(fname);
@@ -69,7 +94,7 @@
 		}
 		for (String m : knownEntries) {
 			// removed from the repository and missing from working dir shall not be reported as 'deleted' 
-			if (dirstate.checkRemoved(m) == null) {
+			if (getDirstate().checkRemoved(m) == null) {
 				inspector.missing(m);
 			}
 		}
@@ -84,9 +109,9 @@
 	//********************************************
 
 	
-	private static void checkLocalStatusAgainstFile(String fname, File f, HgDirstate dirstate, StatusCollector.Inspector inspector) {
+	private void checkLocalStatusAgainstFile(String fname, File f, StatusCollector.Inspector inspector) {
 		HgDirstate.Record r;
-		if ((r = dirstate.checkNormal(fname)) != null) {
+		if ((r = getDirstate().checkNormal(fname)) != null) {
 			// either clean or modified
 			if (f.lastModified() / 1000 == r.time && r.size == f.length()) {
 				inspector.clean(fname);
@@ -94,35 +119,35 @@
 				// FIXME check actual content to avoid false modified files
 				inspector.modified(fname);
 			}
-		} else if ((r = dirstate.checkAdded(fname)) != null) {
+		} else if ((r = getDirstate().checkAdded(fname)) != null) {
 			if (r.name2 == null) {
 				inspector.added(fname);
 			} else {
 				inspector.copied(fname, r.name2);
 			}
-		} else if ((r = dirstate.checkRemoved(fname)) != null) {
+		} else if ((r = getDirstate().checkRemoved(fname)) != null) {
 			inspector.removed(fname);
-		} else if ((r = dirstate.checkMerged(fname)) != null) {
+		} else if ((r = getDirstate().checkMerged(fname)) != null) {
 			inspector.modified(fname);
 		}
 	}
 	
 	// XXX refactor checkLocalStatus methods in more OO way
-	private void checkLocalStatusAgainstBaseRevision(Set<String> baseRevNames, Nodeid nid1, String flags, String fname, File f, HgDirstate dirstate, StatusCollector.Inspector inspector) {
+	private void checkLocalStatusAgainstBaseRevision(Set<String> baseRevNames, Nodeid nid1, String flags, String fname, File f, StatusCollector.Inspector inspector) {
 		// fname is in the dirstate, either Normal, Added, Removed or Merged
 		HgDirstate.Record r;
 		if (nid1 == null) {
 			// normal: added?
 			// added: not known at the time of baseRevision, shall report
 			// merged: was not known, report as added?
-			if ((r = dirstate.checkAdded(fname)) != null) {
+			if ((r = getDirstate().checkAdded(fname)) != null) {
 				if (r.name2 != null && baseRevNames.contains(r.name2)) {
 					baseRevNames.remove(r.name2);
 					inspector.copied(r.name2, fname);
 					return;
 				}
 				// fall-through, report as added
-			} else if (dirstate.checkRemoved(fname) != null) {
+			} else if (getDirstate().checkRemoved(fname) != null) {
 				// removed: removed file was not known at the time of baseRevision, and we should not report it as removed
 				return;
 			}
@@ -130,7 +155,7 @@
 		} else {
 			// was known; check whether clean or modified
 			// when added - seems to be the case of a file added once again, hence need to check if content is different
-			if ((r = dirstate.checkNormal(fname)) != null || (r = dirstate.checkMerged(fname)) != null || (r = dirstate.checkAdded(fname)) != null) {
+			if ((r = getDirstate().checkNormal(fname)) != null || (r = getDirstate().checkMerged(fname)) != null || (r = getDirstate().checkAdded(fname)) != null) {
 				// either clean or modified
 				HgDataFile fileNode = repo.getFileNode(fname);
 				final int lengthAtRevision = fileNode.length(nid1);