changeset 522:2103388d4010 v1.1m2

Expose option to report changesets in reversed order
author Artem Tikhomirov <tikhomirov.artem@gmail.com>
date Wed, 26 Dec 2012 18:14:53 +0100
parents 59e555c85da0
children 9c5af6ed57c3
files src/org/tmatesoft/hg/core/HgIterateDirection.java src/org/tmatesoft/hg/core/HgLogCommand.java test/org/tmatesoft/hg/test/TestHistory.java
diffstat 3 files changed, 75 insertions(+), 44 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/org/tmatesoft/hg/core/HgIterateDirection.java	Wed Dec 26 18:14:53 2012 +0100
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2012 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;
+
+
+/**
+ * Change order changesets are reported to handler
+ * 
+ * @author Artem Tikhomirov
+ * @author TMate Software Ltd.
+ */
+public enum HgIterateDirection {
+	/**
+	 * Natural order, earlier revisions come first
+	 */
+	OldToNew, 
+	
+	/**
+	 * Reversed order, newer revisions come first, much like command-line client does
+	 */
+	NewToOld
+}
\ No newline at end of file
--- a/src/org/tmatesoft/hg/core/HgLogCommand.java	Wed Dec 26 17:51:07 2012 +0100
+++ b/src/org/tmatesoft/hg/core/HgLogCommand.java	Wed Dec 26 18:14:53 2012 +0100
@@ -36,7 +36,6 @@
 
 import org.tmatesoft.hg.internal.AdapterPlug;
 import org.tmatesoft.hg.internal.BatchRangeHelper;
-import org.tmatesoft.hg.internal.Experimental;
 import org.tmatesoft.hg.internal.IntMap;
 import org.tmatesoft.hg.internal.IntVector;
 import org.tmatesoft.hg.internal.Lifecycle;
@@ -91,6 +90,9 @@
 	 * Note, 'hg log --follow' combines both #followHistory and #followAncestry
 	 */
 	private boolean followAncestry;
+
+	private HgIterateDirection iterateDirection = HgIterateDirection.OldToNew;
+
 	private ChangesetTransformer csetTransform;
 	private HgParentChildMap<HgChangelog> parentHelper;
 	
@@ -240,6 +242,19 @@
 	public HgLogCommand file(String file, boolean followCopyRename, boolean followFileAncestry) {
 		return file(Path.create(repo.getToRepoPathHelper().rewrite(file)), followCopyRename, followFileAncestry);
 	}
+	
+	/**
+	 * Specifies order for changesets reported through #execute(...) methods.
+	 * By default, command reports changeset in their natural repository order, older first, 
+	 * newer last (i.e. {@link HgIterateDirection#OldToNew}
+	 * 
+	 * @param order {@link HgIterateDirection#NewToOld} to get newer revisions first
+	 * @return <code>this</code> for convenience
+	 */
+	public HgLogCommand order(HgIterateDirection order) {
+		iterateDirection = order;
+		return this;
+	}
 
 	/**
 	 * Similar to {@link #execute(HgChangesetHandler)}, collects and return result as a list.
@@ -305,12 +320,12 @@
 			filterInsp.changesets(startRev, lastCset);
 			if (file == null) {
 				progressHelper.start(lastCset - startRev + 1);
-				if (iterateDirection == IterateDirection.FromOldToNew) {
+				if (iterateDirection == HgIterateDirection.OldToNew) {
 					filterInsp.delegateTo(csetTransform);
 					repo.getChangelog().range(startRev, lastCset, filterInsp);
 					csetTransform.checkFailure();
 				} else {
-					assert iterateDirection == IterateDirection.FromNewToOld;
+					assert iterateDirection == HgIterateDirection.NewToOld;
 					BatchRangeHelper brh = new BatchRangeHelper(startRev, lastCset, BATCH_SIZE, true);
 					BatchChangesetInspector batchInspector = new BatchChangesetInspector(Math.min(lastCset-startRev+1, BATCH_SIZE));
 					filterInsp.delegateTo(batchInspector);
@@ -338,11 +353,11 @@
 						@SuppressWarnings("unused")
 						List<HistoryNode> fileAncestry = treeBuilder.go(fileNode, curRename.second());
 						int[] commitRevisions = narrowChangesetRange(treeBuilder.getCommitRevisions(), startRev, lastCset);
-						if (iterateDirection == IterateDirection.FromOldToNew) {
+						if (iterateDirection == HgIterateDirection.OldToNew) {
 							repo.getChangelog().range(filterInsp, commitRevisions);
 							csetTransform.checkFailure();
 						} else {
-							assert iterateDirection == IterateDirection.FromNewToOld;
+							assert iterateDirection == HgIterateDirection.NewToOld;
 							// visit one by one in the opposite direction
 							for (int i = commitRevisions.length-1; i >= 0; i--) {
 								int csetWithFileChange = commitRevisions[i];
@@ -353,11 +368,11 @@
 						// report complete file history (XXX may narrow range with [startRev, endRev], but need to go from file rev to link rev)
 						int fileStartRev = 0; //fileNode.getChangesetRevisionIndex(0) >= startRev
 						int fileEndRev = fileNode.getLastRevision();
-						if (iterateDirection == IterateDirection.FromOldToNew) {
+						if (iterateDirection == HgIterateDirection.OldToNew) {
 							fileNode.history(fileStartRev, fileEndRev, filterInsp);
 							csetTransform.checkFailure();
 						} else {
-							assert iterateDirection == IterateDirection.FromNewToOld;
+							assert iterateDirection == HgIterateDirection.NewToOld;
 							BatchRangeHelper brh = new BatchRangeHelper(fileStartRev, fileEndRev, BATCH_SIZE, true);
 							BatchChangesetInspector batchInspector = new BatchChangesetInspector(Math.min(fileEndRev-fileStartRev+1, BATCH_SIZE));
 							filterInsp.delegateTo(batchInspector);
@@ -376,12 +391,12 @@
 						Pair<HgDataFile, Nodeid> nextRename = fileRenames.get(nameIndex+1);
 						HgFileRevision src, dst;
 						// A -> B
-						if (iterateDirection == IterateDirection.FromOldToNew) {
+						if (iterateDirection == HgIterateDirection.OldToNew) {
 							// curRename: A, nextRename: B
 							src = new HgFileRevision(fileNode, curRename.second(), null);
 							dst = new HgFileRevision(nextRename.first(), nextRename.first().getRevision(0), src.getPath());
 						} else {
-							assert iterateDirection == IterateDirection.FromNewToOld;
+							assert iterateDirection == HgIterateDirection.NewToOld;
 							// curRename: B, nextRename: A
 							src = new HgFileRevision(nextRename.first(), nextRename.second(), null);
 							dst = new HgFileRevision(fileNode, fileNode.getRevision(0), src.getPath());
@@ -538,23 +553,6 @@
 		progressHelper.done();
 	}
 	
-	/**
-	 * DO NOT USE THIS METHOD, DEBUG PURPOSES ONLY!!!
-	 */
-	@Experimental(reason="Work in progress")
-	public HgLogCommand debugSwitch1() {
-		// FIXME can't expose iteration direction unless general iteration (changelog, not a file) supports it, too.
-		// however, need to test the code already there, hence this debug switch
-		if (iterateDirection == IterateDirection.FromOldToNew) {
-			iterateDirection = IterateDirection.FromNewToOld;
-		} else {
-			iterateDirection = IterateDirection.FromOldToNew;
-		}
-		return this;
-	}
-	
-	private IterateDirection iterateDirection = IterateDirection.FromOldToNew;
-
 	private static class ReverseIterator<E> implements Iterator<E> {
 		private final ListIterator<E> listIterator;
 		
@@ -614,10 +612,10 @@
 			Nodeid copyRev = fileNode.getCopySourceRevision();
 			fileNode = repo.getFileNode(fp);
 			Pair<HgDataFile, Nodeid> p = new Pair<HgDataFile, Nodeid>(fileNode, copyRev);
-			if (iterateDirection == IterateDirection.FromOldToNew) {
+			if (iterateDirection == HgIterateDirection.OldToNew) {
 				rv.addFirst(p);
 			} else {
-				assert iterateDirection == IterateDirection.FromNewToOld;
+				assert iterateDirection == HgIterateDirection.NewToOld;
 				rv.addLast(p);
 			}
 		};
@@ -809,7 +807,7 @@
 		public void updateJunctionPoint(Pair<HgDataFile, Nodeid> curRename, Pair<HgDataFile, Nodeid> nextRename) {
 			// A (old) renamed to B(new).  A(0..k..n) -> B(0..m). If followAncestry, k == n
 			// curRename.second() points to A(k)
-			if (iterateDirection == IterateDirection.FromOldToNew) {
+			if (iterateDirection == HgIterateDirection.OldToNew) {
 				// looking at A chunk (curRename), nextRename points to B
 				HistoryNode junctionSrc = findJunctionPointInCurrentChunk(curRename.second()); // A(k)
 				HistoryNode junctionDestMock = treeBuildInspector.one(nextRename.first(), 0); // B(0)
@@ -821,7 +819,7 @@
 				// moreover, children of original A(k) (junctionSrc) would list mock B(0) which is undesired once we iterate over real B
 				junctionNode = new HistoryNode(junctionSrc.changeset, junctionSrc.fileRevision, null, null);
 			} else {
-				assert iterateDirection == IterateDirection.FromNewToOld;
+				assert iterateDirection == HgIterateDirection.NewToOld;
 				// looking at B chunk (curRename), nextRename points at A
 				HistoryNode junctionDest = changeHistory.get(0); // B(0)
 				// prepare mock A(k)
@@ -845,7 +843,7 @@
 		public void connectWithLastJunctionPoint(Pair<HgDataFile, Nodeid> curRename, Pair<HgDataFile, Nodeid> prevRename, HgFileRenameHandlerMixin renameHandler) throws HgCallbackTargetException {
 			assert junctionNode != null;
 			// A renamed to B. A(0..k..n) -> B(0..m). If followAncestry: k == n  
-			if (iterateDirection == IterateDirection.FromOldToNew) {
+			if (iterateDirection == HgIterateDirection.OldToNew) {
 				// forward, from old to new:
 				// changeHistory points to B 
 				// Already reported: A(0)..A(n), A(k) is in junctionNode
@@ -859,7 +857,7 @@
 					renameHandler.copy(copiedFrom, copiedTo);
 				}
 			} else {
-				assert iterateDirection == IterateDirection.FromNewToOld;
+				assert iterateDirection == HgIterateDirection.NewToOld;
 				// changeHistory points to A
 				// Already reported B(m), B(m-1)...B(0), B(0) is in junctionNode
 				// Shall connect histories A(k).bind(B(0))
@@ -896,10 +894,10 @@
 		public void dispatchAllChanges() throws HgCallbackTargetException, CancelledException {
 			// XXX shall sort changeHistory according to changeset numbers?
 			Iterator<HistoryNode> it;
-			if (iterateDirection == IterateDirection.FromOldToNew) {
+			if (iterateDirection == HgIterateDirection.OldToNew) {
 				it = changeHistory.listIterator();
 			} else {
-				assert iterateDirection == IterateDirection.FromNewToOld;
+				assert iterateDirection == HgIterateDirection.NewToOld;
 				it = new ReverseIterator<HistoryNode>(changeHistory);
 			}
 			while(it.hasNext()) {
@@ -1234,8 +1232,4 @@
 			}
 		}
 	}
-
-	private enum IterateDirection {
-		FromOldToNew, FromNewToOld
-	}
 }
--- a/test/org/tmatesoft/hg/test/TestHistory.java	Wed Dec 26 17:51:07 2012 +0100
+++ b/test/org/tmatesoft/hg/test/TestHistory.java	Wed Dec 26 18:14:53 2012 +0100
@@ -20,6 +20,7 @@
 import static org.hamcrest.CoreMatchers.is;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
+import static org.tmatesoft.hg.core.HgIterateDirection.NewToOld;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -96,7 +97,7 @@
 		List<HgChangeset> r = new HgLogCommand(repo).execute();
 		report("hg log - COMPLETE REPO HISTORY", r, true);
 		
-		r = new HgLogCommand(repo).debugSwitch1().execute();
+		r = new HgLogCommand(repo).order(NewToOld).execute();
 		report("hg log - COMPLETE REPO HISTORY, FROM NEW TO OLD", r, false);
 	}
 	
@@ -174,7 +175,7 @@
 		//
 		// Direction
 		h = new CollectWithRenameHandler();
-		new HgLogCommand(repo).file(fname2, true, false).debugSwitch1().execute(h);
+		new HgLogCommand(repo).file(fname2, true, false).order(NewToOld).execute(h);
 		// Identical rename shall be reported, at the same moment 
 		errorCollector.assertEquals(1, h.rh.renames.size());
 		rename = h.rh.renames.get(0);
@@ -216,7 +217,7 @@
 		h = new TreeCollectHandler(false);
 		rh = new RenameCollector(h);
 		// h.checkPrevInChildren = true; see above
-		new HgLogCommand(repo).file(fname2, true, false).debugSwitch1().execute(h);
+		new HgLogCommand(repo).file(fname2, true, false).order(NewToOld).execute(h);
 		errorCollector.assertEquals(1, rh.renames.size());
 		rename = rh.renames.get(0);
 		errorCollector.assertEquals(fname1, rename.first().getPath().toString());
@@ -238,7 +239,7 @@
 		//
 		// Direction
 		h = new CollectWithRenameHandler();
-		new HgLogCommand(repo).file(fname2, false, true).debugSwitch1().execute(h);
+		new HgLogCommand(repo).file(fname2, false, true).order(NewToOld).execute(h);
 		report("HgChangesetHandler(renames: false, ancestry:true)", h.getChanges(), fname2Follow, false/*!!!*/, errorCollector);
 		//
 		// TreeChangeHandler - in #testChangesetTreeFollowAncestryNotRenames
@@ -261,7 +262,7 @@
 		h = new TreeCollectHandler(false);
 		rh = new RenameCollector(h);
 		h.checkPrevInChildren = true;
-		new HgLogCommand(repo).file(fname2, false, true).debugSwitch1().execute(h);
+		new HgLogCommand(repo).file(fname2, false, true).order(NewToOld).execute(h);
 		report("HgChangesetTreeHandler(renames: false, ancestry:true)", h.getResult(), fname2Follow, false, errorCollector);
 	}
 
@@ -317,7 +318,7 @@
 		//
 		// Switch direction and compare, order shall match that from console
 		h = new CollectWithRenameHandler();
-		new HgLogCommand(repo).file(fname2, true, true).debugSwitch1().execute(h);
+		new HgLogCommand(repo).file(fname2, true, true).order(NewToOld).execute(h);
 		// Identical rename event shall be reported
 		errorCollector.assertEquals(1, h.rh.renames.size());
 		rename = h.rh.renames.get(0);