changeset 68:0e499fed9b3d

StatusCommand with tests. Extra constants to indicate common revision cases
author Artem Tikhomirov <tikhomirov.artem@gmail.com>
date Sat, 22 Jan 2011 22:11:24 +0100
parents 64bddc2dcc0e
children 5a69397f0f99
files src/com/tmate/hgkit/ll/HgRepository.java src/com/tmate/hgkit/ll/StatusCollector.java src/com/tmate/hgkit/ll/WorkingCopyStatusCollector.java src/org/tmatesoft/hg/core/StatusCommand.java test/org/tmatesoft/hg/test/TestStatus.java
diffstat 5 files changed, 146 insertions(+), 19 deletions(-) [+]
line wrap: on
line diff
--- a/src/com/tmate/hgkit/ll/HgRepository.java	Fri Jan 21 19:21:43 2011 +0100
+++ b/src/com/tmate/hgkit/ll/HgRepository.java	Sat Jan 22 22:11:24 2011 +0100
@@ -14,6 +14,8 @@
 public abstract class HgRepository {
 
 	public static final int TIP = -1;
+	public static final int BAD_REVISION = Integer.MIN_VALUE;
+	public static final int WORKING_COPY = -2;
 
 	// temp aux marker method
 	public static IllegalStateException notImplemented() {
--- a/src/com/tmate/hgkit/ll/StatusCollector.java	Fri Jan 21 19:21:43 2011 +0100
+++ b/src/com/tmate/hgkit/ll/StatusCollector.java	Sat Jan 22 22:11:24 2011 +0100
@@ -3,6 +3,9 @@
  */
 package com.tmate.hgkit.ll;
 
+import static com.tmate.hgkit.ll.HgRepository.BAD_REVISION;
+import static com.tmate.hgkit.ll.HgRepository.TIP;
+
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
@@ -26,7 +29,7 @@
 		cache = new HashMap<Integer, ManifestRevisionInspector>();
 		ManifestRevisionInspector emptyFakeState = new ManifestRevisionInspector(-1, -1);
 		emptyFakeState.begin(-1, null);
-		emptyFakeState.end(-1);
+		emptyFakeState.end(-1); // FIXME HgRepo.TIP == -1 as well, need to distinguish fake "prior to first" revision from "the very last" 
 		cache.put(-1, emptyFakeState);
 	}
 	
@@ -68,6 +71,12 @@
 		if (inspector instanceof Record) {
 			((Record) inspector).init(rev1, rev2, this);
 		}
+		if (rev1 == TIP) {
+			rev1 = repo.getManifest().getRevisionCount() - 1;
+		}
+		if (rev2 == TIP) {
+			rev2 = repo.getManifest().getRevisionCount() - 1; // XXX add Revlog.tip() func ? 
+		}
 		// in fact, rev1 and rev2 are often next (or close) to each other,
 		// thus, we can optimize Manifest reads here (manifest.walk(rev1, rev2))
 		ManifestRevisionInspector r1, r2;
@@ -145,12 +154,18 @@
 		}
 		
 		public Nodeid nodeidBeforeChange(String fname) {
+			if (statusHelper == null || startRev == BAD_REVISION) {
+				return null;
+			}
 			if ((modified == null || !modified.contains(fname)) && (removed == null || !removed.contains(fname))) {
 				return null;
 			}
 			return statusHelper.raw(startRev).nodeid(startRev, fname);
 		}
 		public Nodeid nodeidAfterChange(String fname) {
+			if (statusHelper == null || endRev == BAD_REVISION) {
+				return null;
+			}
 			if ((modified == null || !modified.contains(fname)) && (added == null || !added.contains(fname))) {
 				return null;
 			}
--- a/src/com/tmate/hgkit/ll/WorkingCopyStatusCollector.java	Fri Jan 21 19:21:43 2011 +0100
+++ b/src/com/tmate/hgkit/ll/WorkingCopyStatusCollector.java	Sat Jan 22 22:11:24 2011 +0100
@@ -3,6 +3,7 @@
  */
 package com.tmate.hgkit.ll;
 
+import static com.tmate.hgkit.ll.HgRepository.BAD_REVISION;
 import static com.tmate.hgkit.ll.HgRepository.TIP;
 
 import java.io.BufferedInputStream;
@@ -54,7 +55,13 @@
 	public void walk(int baseRevision, StatusCollector.Inspector inspector) {
 		final HgIgnore hgIgnore = ((LocalHgRepo) repo).loadIgnore(); // FIXME hack
 		TreeSet<String> knownEntries = getDirstate().all();
-		final boolean isTipBase = baseRevision == TIP || baseRevision == repo.getManifest().getRevisionCount();
+		final boolean isTipBase;
+		if (baseRevision == TIP) {
+			baseRevision = repo.getManifest().getRevisionCount() - 1;
+			isTipBase = true;
+		} else {
+			isTipBase = baseRevision == repo.getManifest().getRevisionCount() - 1;
+		}
 		StatusCollector.ManifestRevisionInspector collect = null;
 		Set<String> baseRevFiles = Collections.emptySet();
 		if (!isTipBase) {
@@ -66,6 +73,10 @@
 			}
 			baseRevFiles = new TreeSet<String>(collect.files(baseRevision));
 		}
+		if (inspector instanceof StatusCollector.Record) {
+			StatusCollector sc = baseRevisionCollector == null ? new StatusCollector(repo) : baseRevisionCollector;
+			((StatusCollector.Record) inspector).init(baseRevision, BAD_REVISION, sc);
+		}
 		repoWalker.reset();
 		while (repoWalker.hasNext()) {
 			repoWalker.next();
--- a/src/org/tmatesoft/hg/core/StatusCommand.java	Fri Jan 21 19:21:43 2011 +0100
+++ b/src/org/tmatesoft/hg/core/StatusCommand.java	Sat Jan 22 22:11:24 2011 +0100
@@ -16,9 +16,19 @@
  */
 package org.tmatesoft.hg.core;
 
+import static com.tmate.hgkit.ll.HgRepository.BAD_REVISION;
+import static com.tmate.hgkit.ll.HgRepository.TIP;
+import static com.tmate.hgkit.ll.HgRepository.WORKING_COPY;
+
 import org.tmatesoft.hg.core.Path.Matcher;
+import org.tmatesoft.hg.util.PathPool;
 
+import com.tmate.hgkit.fs.FileWalker;
 import com.tmate.hgkit.ll.HgRepository;
+import com.tmate.hgkit.ll.LocalHgRepo;
+import com.tmate.hgkit.ll.StatusCollector;
+import com.tmate.hgkit.ll.WorkingCopyStatusCollector;
+import com.tmate.hgkit.ll.StatusCollector.Record;
 
 /**
  *
@@ -28,22 +38,55 @@
 public class StatusCommand {
 	private final HgRepository repo;
 
-	private boolean needClean = false;
-	private boolean needIgnored = false;
+	private boolean needModified;
+	private boolean needAdded;
+	private boolean needRemoved;
+	private boolean needUnknown;
+	private boolean needMissing;
+	private boolean needClean;
+	private boolean needIgnored;
 	private Matcher matcher;
-	private int startRevision;
-	private Integer endRevision; // need three states, set, -1 or actual rev number
+	private int startRevision = TIP;
+	private int endRevision = WORKING_COPY; 
 	private boolean visitSubRepo = true;
 
-	public StatusCommand(HgRepository hgRepo) {
-		this.repo = hgRepo;
+	public StatusCommand(HgRepository hgRepo) { 
+		repo = hgRepo;
+		defaults();
 	}
 
-	public StatusCommand all() {
-		needClean = true;
+	public StatusCommand defaults() {
+		needModified = needAdded = needRemoved = needUnknown = needMissing = true;
+		needClean = needIgnored = false;
 		return this;
 	}
+	public StatusCommand all() {
+		needModified = needAdded = needRemoved = needUnknown = needMissing = true;
+		needClean = needIgnored = true;
+		return this;
+	}
+	
 
+	public StatusCommand modified(boolean include) {
+		needModified = include;
+		return this;
+	}
+	public StatusCommand added(boolean include) {
+		needAdded = include;
+		return this;
+	}
+	public StatusCommand removed(boolean include) {
+		needRemoved = include;
+		return this;
+	}
+	public StatusCommand deleted(boolean include) {
+		needMissing = include;
+		return this;
+	}
+	public StatusCommand unknown(boolean include) {
+		needUnknown = include;
+		return this;
+	}
 	public StatusCommand clean(boolean include) {
 		needClean = include;
 		return this;
@@ -53,17 +96,36 @@
 		return this;
 	}
 	
-	// if set, either base:revision or base:workingdir
+	/**
+	 * if set, either base:revision or base:workingdir
+	 * to unset, pass {@link HgRepository#TIP} or {@link HgRepository#BAD_REVISION}
+	 * @param revision
+	 * @return
+	 */
+	
 	public StatusCommand base(int revision) {
+		if (revision == WORKING_COPY) {
+			throw new IllegalArgumentException();
+		}
+		if (revision == BAD_REVISION) {
+			revision = TIP;
+		}
 		startRevision = revision;
 		return this;
 	}
 	
-	// revision without base == --change
+	/**
+	 * Revision without base == --change
+	 * Pass {@link HgRepository#WORKING_COPY} or {@link HgRepository#BAD_REVISION} to reset
+	 * @param revision
+	 * @return
+	 */
 	public StatusCommand revision(int revision) {
-		// XXX how to clear endRevision, if needed.
-		// Perhaps, use of WC_REVISION or BAD_REVISION == -2 or Int.MIN_VALUE?
-		endRevision = new Integer(revision);
+		if (revision == BAD_REVISION) {
+			revision = WORKING_COPY;
+		}
+		// XXX negative values, except for predefined constants, shall throw IAE.
+		endRevision = revision;
 		return this;
 	}
 	
@@ -77,7 +139,21 @@
 		throw HgRepository.notImplemented();
 	}
 	
-	public void execute() {
-		throw HgRepository.notImplemented();
+	public void execute(StatusCollector.Inspector inspector) {
+		StatusCollector sc = new StatusCollector(repo); // TODO from CommandContext
+//		StatusCollector.Record r = new StatusCollector.Record(); // XXX use own inspector not to collect entries that
+		// are not interesting or do not match name
+		if (endRevision == WORKING_COPY) {
+			WorkingCopyStatusCollector wcsc = new WorkingCopyStatusCollector(repo, ((LocalHgRepo) repo).createWorkingDirWalker());
+			wcsc.setBaseRevisionCollector(sc);
+			wcsc.walk(startRevision, inspector);
+		} else {
+			if (startRevision == TIP) {
+				sc.change(endRevision, inspector);
+			} else {
+				sc.walk(startRevision, endRevision, inspector);
+			}
+		}
+//		PathPool pathHelper = new PathPool(repo.getPathHelper()); // TODO from CommandContext
 	}
 }
--- a/test/org/tmatesoft/hg/test/TestStatus.java	Fri Jan 21 19:21:43 2011 +0100
+++ b/test/org/tmatesoft/hg/test/TestStatus.java	Sat Jan 22 22:11:24 2011 +0100
@@ -16,11 +16,15 @@
  */
 package org.tmatesoft.hg.test;
 
+import static com.tmate.hgkit.ll.HgRepository.TIP;
+
 import java.io.File;
 import java.util.Collection;
 import java.util.LinkedList;
 import java.util.List;
 
+import org.tmatesoft.hg.core.StatusCommand;
+
 import com.tmate.hgkit.fs.FileWalker;
 import com.tmate.hgkit.fs.RepositoryLookup;
 import com.tmate.hgkit.ll.HgRepository;
@@ -34,9 +38,9 @@
  */
 public class TestStatus {
 
+	private final HgRepository repo;
 	private StatusOutputParser statusParser;
 	private ExecHelper eh;
-	private final HgRepository repo;
 
 	public static void main(String[] args) throws Exception {
 		HgRepository repo = new RepositoryLookup().detectFromWorkingDir();
@@ -53,6 +57,7 @@
 	
 	public void testLowLevel() throws Exception {
 		final WorkingCopyStatusCollector wcc = new WorkingCopyStatusCollector(repo, new FileWalker(new File(System.getProperty("user.dir"))));
+		statusParser.reset();
 		eh.run("hg", "status", "-A");
 		StatusCollector.Record r = wcc.status(HgRepository.TIP);
 		report("hg status -A", r, statusParser);
@@ -71,7 +76,25 @@
 	}
 	
 	public void testStatusCommand() throws Exception {
-		throw HgRepository.notImplemented();
+		final StatusCommand sc = new StatusCommand(repo).all();
+		StatusCollector.Record r;
+		statusParser.reset();
+		eh.run("hg", "status", "-A");
+		sc.execute(r = new StatusCollector.Record());
+		report("hg status -A", r, statusParser);
+		//
+		statusParser.reset();
+		int revision = 3;
+		eh.run("hg", "status", "-A", "--rev", String.valueOf(revision));
+		sc.base(revision).execute(r = new StatusCollector.Record());
+		report("status -A --rev " + revision, r, statusParser);
+		//
+		statusParser.reset();
+		eh.run("hg", "status", "-A", "--change", String.valueOf(revision));
+		sc.base(TIP).revision(revision).execute(r = new StatusCollector.Record());
+		report("status -A --change " + revision, r, statusParser);
+		
+		// TODO check not -A, but defaults()/custom set of modifications 
 	}
 	
 	private static void report(String what, StatusCollector.Record r, StatusOutputParser statusParser) {