diff src/org/tmatesoft/hg/core/HgStatusCommand.java @ 131:aa1629f36482

Renamed .core classes to start with Hg prefix
author Artem Tikhomirov <tikhomirov.artem@gmail.com>
date Wed, 16 Feb 2011 20:47:56 +0100
parents src/org/tmatesoft/hg/core/StatusCommand.java@44b97930570c
children 4a948ec83980
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/org/tmatesoft/hg/core/HgStatusCommand.java	Wed Feb 16 20:47:56 2011 +0100
@@ -0,0 +1,265 @@
+/*
+ * Copyright (c) 2011 TMate Software Ltd
+ *  
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * For information on how to redistribute this software under
+ * the terms of a license other than GNU General Public License
+ * contact TMate Software at support@hg4j.com
+ */
+package org.tmatesoft.hg.core;
+
+import static org.tmatesoft.hg.core.HgStatus.Kind.*;
+import static org.tmatesoft.hg.repo.HgRepository.*;
+
+import java.util.ConcurrentModificationException;
+
+import org.tmatesoft.hg.core.Path.Matcher;
+import org.tmatesoft.hg.internal.ChangelogHelper;
+import org.tmatesoft.hg.repo.HgRepository;
+import org.tmatesoft.hg.repo.HgStatusCollector;
+import org.tmatesoft.hg.repo.HgStatusInspector;
+import org.tmatesoft.hg.repo.HgWorkingCopyStatusCollector;
+
+/**
+ * Command to obtain file status information, 'hg status' counterpart. 
+ * 
+ * @author Artem Tikhomirov
+ * @author TMate Software Ltd.
+ */
+public class HgStatusCommand {
+	private final HgRepository repo;
+
+	private int startRevision = TIP;
+	private int endRevision = WORKING_COPY; 
+	private boolean visitSubRepo = true;
+	
+	private final Mediator mediator = new Mediator();
+
+	public HgStatusCommand(HgRepository hgRepo) { 
+		repo = hgRepo;
+		defaults();
+	}
+
+	public HgStatusCommand defaults() {
+		final Mediator m = mediator;
+		m.needModified = m.needAdded = m.needRemoved = m.needUnknown = m.needMissing = true;
+		m.needCopies = m.needClean = m.needIgnored = false;
+		return this;
+	}
+	public HgStatusCommand all() {
+		final Mediator m = mediator;
+		m.needModified = m.needAdded = m.needRemoved = m.needUnknown = m.needMissing = true;
+		m.needCopies = m.needClean = m.needIgnored = true;
+		return this;
+	}
+	
+
+	public HgStatusCommand modified(boolean include) {
+		mediator.needModified = include;
+		return this;
+	}
+	public HgStatusCommand added(boolean include) {
+		mediator.needAdded = include;
+		return this;
+	}
+	public HgStatusCommand removed(boolean include) {
+		mediator.needRemoved = include;
+		return this;
+	}
+	public HgStatusCommand deleted(boolean include) {
+		mediator.needMissing = include;
+		return this;
+	}
+	public HgStatusCommand unknown(boolean include) {
+		mediator.needUnknown = include;
+		return this;
+	}
+	public HgStatusCommand clean(boolean include) {
+		mediator.needClean = include;
+		return this;
+	}
+	public HgStatusCommand ignored(boolean include) {
+		mediator.needIgnored = include;
+		return this;
+	}
+	
+	/**
+	 * if set, either base:revision or base:workingdir
+	 * to unset, pass {@link HgRepository#TIP} or {@link HgRepository#BAD_REVISION}
+	 * @param revision
+	 * @return
+	 */
+	
+	public HgStatusCommand base(int revision) {
+		if (revision == WORKING_COPY) {
+			throw new IllegalArgumentException();
+		}
+		if (revision == BAD_REVISION) {
+			revision = TIP;
+		}
+		startRevision = revision;
+		return this;
+	}
+	
+	/**
+	 * Revision without base == --change
+	 * Pass {@link HgRepository#WORKING_COPY} or {@link HgRepository#BAD_REVISION} to reset
+	 * @param revision
+	 * @return
+	 */
+	public HgStatusCommand revision(int revision) {
+		if (revision == BAD_REVISION) {
+			revision = WORKING_COPY;
+		}
+		// XXX negative values, except for predefined constants, shall throw IAE.
+		endRevision = revision;
+		return this;
+	}
+	
+	// pass null to reset
+	public HgStatusCommand match(Path.Matcher pathMatcher) {
+		mediator.matcher = pathMatcher;
+		return this;
+	}
+
+	public HgStatusCommand subrepo(boolean visit) {
+		visitSubRepo  = visit;
+		throw HgRepository.notImplemented();
+	}
+
+	/**
+	 * Perform status operation according to parameters set.
+	 *  
+	 * @param handler callback to get status information
+	 * @throws IllegalArgumentException if handler is <code>null</code>
+	 * @throws ConcurrentModificationException if this command already runs (i.e. being used from another thread)
+	 */
+	public void execute(Handler statusHandler) {
+		if (statusHandler == null) {
+			throw new IllegalArgumentException();
+		}
+		if (mediator.busy()) {
+			throw new ConcurrentModificationException();
+		}
+		HgStatusCollector sc = new HgStatusCollector(repo); // TODO from CommandContext
+//		PathPool pathHelper = new PathPool(repo.getPathHelper()); // TODO from CommandContext
+		try {
+			// XXX if I need a rough estimation (for ProgressMonitor) of number of work units,
+			// I may use number of files in either rev1 or rev2 manifest edition
+			mediator.start(statusHandler, new ChangelogHelper(repo, startRevision));
+			if (endRevision == WORKING_COPY) {
+				HgWorkingCopyStatusCollector wcsc = new HgWorkingCopyStatusCollector(repo);
+				wcsc.setBaseRevisionCollector(sc);
+				wcsc.walk(startRevision, mediator);
+			} else {
+				if (startRevision == TIP) {
+					sc.change(endRevision, mediator);
+				} else {
+					sc.walk(startRevision, endRevision, mediator);
+				}
+			}
+		} finally {
+			mediator.done();
+		}
+	}
+
+	public interface Handler {
+		void handleStatus(HgStatus s);
+	}
+
+	private class Mediator implements HgStatusInspector {
+		boolean needModified;
+		boolean needAdded;
+		boolean needRemoved;
+		boolean needUnknown;
+		boolean needMissing;
+		boolean needClean;
+		boolean needIgnored;
+		boolean needCopies;
+		Matcher matcher;
+		Handler handler;
+		private ChangelogHelper logHelper;
+
+		Mediator() {
+		}
+		
+		public void start(Handler h, ChangelogHelper changelogHelper) {
+			handler = h;
+			logHelper = changelogHelper;
+		}
+
+		public void done() {
+			handler = null;
+			logHelper = null;
+		}
+		
+		public boolean busy() {
+			return handler != null;
+		}
+
+		public void modified(Path fname) {
+			if (needModified) {
+				if (matcher == null || matcher.accept(fname)) {
+					handler.handleStatus(new HgStatus(Modified, fname, logHelper));
+				}
+			}
+		}
+		public void added(Path fname) {
+			if (needAdded) {
+				if (matcher == null || matcher.accept(fname)) {
+					handler.handleStatus(new HgStatus(Added, fname, logHelper));
+				}
+			}
+		}
+		public void removed(Path fname) {
+			if (needRemoved) {
+				if (matcher == null || matcher.accept(fname)) {
+					handler.handleStatus(new HgStatus(Removed, fname, logHelper));
+				}
+			}
+		}
+		public void copied(Path fnameOrigin, Path fnameAdded) {
+			if (needCopies) {
+				if (matcher == null || matcher.accept(fnameAdded)) {
+					handler.handleStatus(new HgStatus(Added, fnameAdded, fnameOrigin, logHelper));
+				}
+			}
+		}
+		public void missing(Path fname) {
+			if (needMissing) {
+				if (matcher == null || matcher.accept(fname)) {
+					handler.handleStatus(new HgStatus(Missing, fname, logHelper));
+				}
+			}
+		}
+		public void unknown(Path fname) {
+			if (needUnknown) {
+				if (matcher == null || matcher.accept(fname)) {
+					handler.handleStatus(new HgStatus(Unknown, fname, logHelper));
+				}
+			}
+		}
+		public void clean(Path fname) {
+			if (needClean) {
+				if (matcher == null || matcher.accept(fname)) {
+					handler.handleStatus(new HgStatus(Clean, fname, logHelper));
+				}
+			}
+		}
+		public void ignored(Path fname) {
+			if (needIgnored) {
+				if (matcher == null || matcher.accept(fname)) {
+					handler.handleStatus(new HgStatus(Ignored, fname, logHelper));
+				}
+			}
+		}
+	}
+}