diff src/com/tmate/hgkit/ll/WorkingCopyStatusCollector.java @ 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 a47530a2ea12
line wrap: on
line diff
--- 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);