changeset 206:63c9fed4369e

Sample command line tools for incoming/outgoing to use commands
author Artem Tikhomirov <tikhomirov.artem@gmail.com>
date Thu, 28 Apr 2011 02:47:44 +0200
parents ffc5f6d59f7e
children 1bf0a5af2d5d
files cmdline/org/tmatesoft/hg/console/ChangesetDumpHandler.java cmdline/org/tmatesoft/hg/console/Incoming.java cmdline/org/tmatesoft/hg/console/Log.java cmdline/org/tmatesoft/hg/console/Outgoing.java src/org/tmatesoft/hg/core/HgOutgoingCommand.java src/org/tmatesoft/hg/internal/RepositoryComparator.java
diffstat 6 files changed, 233 insertions(+), 234 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cmdline/org/tmatesoft/hg/console/ChangesetDumpHandler.java	Thu Apr 28 02:47:44 2011 +0200
@@ -0,0 +1,165 @@
+/*
+ * 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.console;
+
+import java.util.Formatter;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.tmatesoft.hg.core.HgChangeset;
+import org.tmatesoft.hg.core.HgChangesetHandler;
+import org.tmatesoft.hg.core.Nodeid;
+import org.tmatesoft.hg.core.HgLogCommand.FileRevision;
+import org.tmatesoft.hg.repo.HgRepository;
+import org.tmatesoft.hg.util.Path;
+
+/**
+ * 
+ * @author Artem Tikhomirov
+ * @author TMate Software Ltd.
+ */
+public class ChangesetDumpHandler implements HgChangesetHandler {
+	// params
+	private boolean complete = false; // roughly --debug
+	private boolean reverseOrder = false;
+	private boolean verbose = true; // roughly -v
+	// own
+	private LinkedList<String> l = new LinkedList<String>();
+	private final HgRepository repo;
+	private final int tip;
+
+	public ChangesetDumpHandler(HgRepository hgRepo) {
+		repo = hgRepo;
+		tip = hgRepo.getChangelog().getLastRevision();
+	}
+
+	public ChangesetDumpHandler complete(boolean b) {
+		complete = b;
+		return this;
+	}
+
+	public ChangesetDumpHandler reversed(boolean b) {
+		reverseOrder = b;
+		return this;
+	}
+
+	public ChangesetDumpHandler verbose(boolean b) {
+		verbose = b;
+		return this;
+	}
+
+	public void next(HgChangeset changeset) {
+		final String s = print(changeset);
+		if (reverseOrder) {
+			// XXX in fact, need to insert s into l according to changeset.getRevision()
+			// because when file history is being followed, revisions of the original file (with smaller revNumber)
+			// are reported *after* revisions of present file and with addFirst appear above them
+			l.addFirst(s);
+		} else {
+			System.out.print(s);
+		}
+	}
+
+	public void done() {
+		if (!reverseOrder) {
+			return;
+		}
+		for (String s : l) {
+			System.out.print(s);
+		}
+		l.clear();
+	}
+
+	private String print(HgChangeset cset) {
+		StringBuilder sb = new StringBuilder();
+		Formatter f = new Formatter(sb);
+		final Nodeid csetNodeid = cset.getNodeid();
+		f.format("changeset:   %d:%s\n", cset.getRevision(), complete ? csetNodeid : csetNodeid.shortNotation());
+		if (cset.getRevision() == tip || repo.getTags().isTagged(csetNodeid)) {
+
+			sb.append("tag:         ");
+			for (String t : repo.getTags().tags(csetNodeid)) {
+				sb.append(t);
+				sb.append(' ');
+			}
+			if (cset.getRevision() == tip) {
+				sb.append("tip");
+			}
+			sb.append('\n');
+		}
+		if (complete) {
+			Nodeid p1 = cset.getFirstParentRevision();
+			Nodeid p2 = cset.getSecondParentRevision();
+			int p1x = p1 == Nodeid.NULL ? -1 : repo.getChangelog().getLocalRevision(p1);
+			int p2x = p2 == Nodeid.NULL ? -1 : repo.getChangelog().getLocalRevision(p2);
+			int mx = repo.getManifest().getLocalRevision(cset.getManifestRevision());
+			f.format("parent:      %d:%s\nparent:      %d:%s\nmanifest:    %d:%s\n", p1x, p1, p2x, p2, mx, cset.getManifestRevision());
+		}
+		f.format("user:        %s\ndate:        %s\n", cset.getUser(), cset.getDate());
+		if (!complete && verbose) {
+			final List<Path> files = cset.getAffectedFiles();
+			sb.append("files:      ");
+			for (Path s : files) {
+				sb.append(' ');
+				sb.append(s);
+			}
+			sb.append('\n');
+		}
+		if (complete) {
+			if (!cset.getModifiedFiles().isEmpty()) {
+				sb.append("files:      ");
+				for (FileRevision s : cset.getModifiedFiles()) {
+					sb.append(' ');
+					sb.append(s.getPath());
+				}
+				sb.append('\n');
+			}
+			if (!cset.getAddedFiles().isEmpty()) {
+				sb.append("files+:     ");
+				for (FileRevision s : cset.getAddedFiles()) {
+					sb.append(' ');
+					sb.append(s.getPath());
+				}
+				sb.append('\n');
+			}
+			if (!cset.getRemovedFiles().isEmpty()) {
+				sb.append("files-:     ");
+				for (Path s : cset.getRemovedFiles()) {
+					sb.append(' ');
+					sb.append(s);
+				}
+				sb.append('\n');
+			}
+			// if (cset.extras() != null) {
+			// sb.append("extra:      ");
+			// for (Map.Entry<String, String> e : cset.extras().entrySet()) {
+			// sb.append(' ');
+			// sb.append(e.getKey());
+			// sb.append('=');
+			// sb.append(e.getValue());
+			// }
+			// sb.append('\n');
+			// }
+		}
+		if (complete || verbose) {
+			f.format("description:\n%s\n\n", cset.getComment());
+		} else {
+			f.format("summary:     %s\n\n", cset.getComment());
+		}
+		return sb.toString();
+	}
+}
--- a/cmdline/org/tmatesoft/hg/console/Incoming.java	Thu Apr 28 02:00:42 2011 +0200
+++ b/cmdline/org/tmatesoft/hg/console/Incoming.java	Thu Apr 28 02:47:44 2011 +0200
@@ -22,27 +22,19 @@
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.LinkedHashMap;
-import java.util.LinkedHashSet;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map.Entry;
 
-import org.tmatesoft.hg.console.Outgoing.ChangesetFormatter;
-import org.tmatesoft.hg.core.HgBadStateException;
+import org.tmatesoft.hg.core.HgIncomingCommand;
+import org.tmatesoft.hg.core.HgRepoFacade;
 import org.tmatesoft.hg.core.Nodeid;
-import org.tmatesoft.hg.internal.RepositoryComparator;
-import org.tmatesoft.hg.internal.RepositoryComparator.BranchChain;
-import org.tmatesoft.hg.repo.HgBundle;
-import org.tmatesoft.hg.repo.HgChangelog;
-import org.tmatesoft.hg.repo.HgChangelog.RawChangeset;
 import org.tmatesoft.hg.repo.HgLookup;
 import org.tmatesoft.hg.repo.HgRemoteRepository;
-import org.tmatesoft.hg.repo.HgRepository;
 
 
 /**
- * WORK IN PROGRESS, DO NOT USE
- * hg incoming counterpart
+ * <em>hg incoming</em> counterpart
  * 
  * @author Artem Tikhomirov
  * @author TMate Software Ltd.
@@ -55,66 +47,35 @@
 			return;
 		}
 		Options cmdLineOpts = Options.parse(args);
-		final HgRepository hgRepo = cmdLineOpts.findRepository();
-		if (hgRepo.isInvalid()) {
-			System.err.printf("Can't find repository in: %s\n", hgRepo.getLocation());
+		HgRepoFacade hgRepo = new HgRepoFacade();
+		if (!hgRepo.init(cmdLineOpts.findRepository())) {
+			System.err.printf("Can't find repository in: %s\n", hgRepo.getRepository().getLocation());
 			return;
 		}
-		HgRemoteRepository hgRemote = new HgLookup().detectRemote(cmdLineOpts.getSingle(""), hgRepo);
+		HgRemoteRepository hgRemote = new HgLookup().detectRemote(cmdLineOpts.getSingle(""), hgRepo.getRepository());
 		if (hgRemote.isInvalid()) {
 			System.err.printf("Remote repository %s is not valid", hgRemote.getLocation());
 			return;
 		}
-		//
-		// in fact, all we need from changelog is set of all nodeids. However, since ParentWalker reuses same Nodeids, it's not too expensive
-		// to reuse it here, XXX although later this may need to be refactored
-		final HgChangelog.ParentWalker pw = hgRepo.getChangelog().new ParentWalker();
-		pw.init();
+		HgIncomingCommand cmd = hgRepo.createIncomingCommand();
+		cmd.against(hgRemote);
 		//
-		RepositoryComparator repoCompare = new RepositoryComparator(pw, hgRemote);
-		repoCompare.compare(null);
-		List<BranchChain> missingBranches = repoCompare.calculateMissingBranches();
-		final LinkedHashSet<Nodeid> common = new LinkedHashSet<Nodeid>();
-		// XXX common can be obtained from repoCompare, but at the moment it would almost duplicate work of calculateMissingBranches
-		// once I refactor latter, common shall be taken from repoCompare.
-		for (BranchChain bc : missingBranches) {
-			bc.dump();
-			common.add(bc.branchRoot); // common known node
-			List<Nodeid> missing = repoCompare.visitBranches(bc);
-			assert bc.branchRoot.equals(missing.get(0)); 
-			missing.remove(0);
-			Collections.reverse(missing); // useful to test output, from newer to older
-			System.out.println("Nodes to fetch in this branch:");
-			for (Nodeid n : missing) {
-				if (pw.knownNode(n)) {
-					System.out.println("Erroneous to fetch:" + n);
-				} else {
-					System.out.println(n);
-				}
-			}
-			System.out.println("Branch done");
-		}
+		List<Nodeid> missing = cmd.executeLite(null);
+		Collections.reverse(missing); // useful to test output, from newer to older
+		Outgoing.dump("Nodes to fetch:", missing);
 		//
 		// Complete
-		HgBundle changegroup = hgRemote.getChanges(new LinkedList<Nodeid>(common));
-		changegroup.changes(hgRepo, new HgChangelog.Inspector() {
-			private int localIndex;
-			private final ChangesetFormatter formatter = new ChangesetFormatter();
-			
-			public void next(int revisionNumber, Nodeid nodeid, RawChangeset cset) {
-				if (pw.knownNode(nodeid)) {
-					if (!common.contains(nodeid)) {
-						throw new HgBadStateException("Bundle shall not report known nodes other than roots we've supplied");
-					}
-					localIndex = hgRepo.getChangelog().getLocalRevision(nodeid);
-					return;
-				}
-				System.out.println(formatter.simple(++localIndex, nodeid, cset));
-			}
-		});
+		final ChangesetDumpHandler h = new ChangesetDumpHandler(hgRepo.getRepository());
+		h.complete(false); // this option looks up index of parent revision, done via repo.changelog (which doesn't have any of these new revisions)
+		// this can be fixed by tracking all nodeid->revision idx inside ChangesetDumpHandler, and refer to repo.changelog only when that mapping didn't work
+		h.verbose(cmdLineOpts.getBoolean("-v", "--verbose"));
+		cmd.executeFull(h);
 	}
 	
 
+	/*
+	 * This is for investigation purposes only
+	 */
 	private static class SequenceConstructor {
 
 		private int[] between(int root, int head) {
--- a/cmdline/org/tmatesoft/hg/console/Log.java	Thu Apr 28 02:00:42 2011 +0200
+++ b/cmdline/org/tmatesoft/hg/console/Log.java	Thu Apr 28 02:47:44 2011 +0200
@@ -16,17 +16,12 @@
  */
 package org.tmatesoft.hg.console;
 
-import java.util.Formatter;
-import java.util.LinkedList;
 import java.util.List;
 
-import org.tmatesoft.hg.core.HgChangeset;
 import org.tmatesoft.hg.core.HgLogCommand;
 import org.tmatesoft.hg.core.HgLogCommand.FileRevision;
-import org.tmatesoft.hg.core.Nodeid;
 import org.tmatesoft.hg.repo.HgDataFile;
 import org.tmatesoft.hg.repo.HgRepository;
-import org.tmatesoft.hg.util.Path;
 
 
 /**
@@ -45,9 +40,10 @@
 			return;
 		}
 		final Dump dump = new Dump(hgRepo);
-		dump.complete = cmdLineOpts.getBoolean("--debug");
-		dump.verbose = cmdLineOpts.getBoolean("-v", "--verbose");
-		dump.reverseOrder = true;
+		dump.complete(cmdLineOpts.getBoolean("--debug"));
+		dump.verbose(cmdLineOpts.getBoolean("-v", "--verbose"));
+		final boolean reverseOrder = true;
+		dump.reversed(reverseOrder);
 		HgLogCommand cmd = new HgLogCommand(hgRepo);
 		for (String u : cmdLineOpts.getList("-u", "--user")) {
 			cmd.user(u);
@@ -69,13 +65,13 @@
 				// in fact, external (to dump inspector) --limit processing yelds incorrect results when other args
 				// e.g. -u or -b are used (i.e. with -u shall give <limit> csets with user, not check last <limit> csets for user 
 				int[] r = new int[] { 0, hgRepo.getChangelog().getRevisionCount() };
-				if (fixRange(r, dump.reverseOrder, limit) == 0) {
+				if (fixRange(r, reverseOrder, limit) == 0) {
 					System.out.println("No changes");
 					return;
 				}
 				cmd.range(r[0], r[1]).execute(dump);
 			}
-			dump.complete();
+			dump.done();
 		} else {
 			for (String fname : files) {
 				HgDataFile f1 = hgRepo.getFileNode(fname);
@@ -84,13 +80,13 @@
 					cmd.file(f1.getPath(), true).execute(dump);
 				} else {
 					int[] r = new int[] { 0, f1.getRevisionCount() };
-					if (fixRange(r, dump.reverseOrder, limit) == 0) {
+					if (fixRange(r, reverseOrder, limit) == 0) {
 						System.out.println("No changes");
 						continue;
 					}
 					cmd.range(r[0], r[1]).file(f1.getPath(), true).execute(dump);
 				}
-				dump.complete();
+				dump.done();
 			}
 		}
 //		cmd = null;
@@ -113,132 +109,14 @@
 		return rv;
 	}
 
-	private static final class Dump implements HgLogCommand.FileHistoryHandler {
-		// params
-		boolean complete = false; // roughly --debug
-		boolean reverseOrder = false;
-		boolean verbose = true; // roughly -v
-		// own
-		private LinkedList<String> l = new LinkedList<String>();
-		private final HgRepository repo;
-//		private HgChangelog.ParentWalker changelogWalker;
-		private final int tip ;
+	private static final class Dump extends ChangesetDumpHandler implements HgLogCommand.FileHistoryHandler {
 
 		public Dump(HgRepository hgRepo) {
-			repo = hgRepo;
-			tip = hgRepo.getChangelog().getLastRevision();
+			super(hgRepo);
 		}
 		
 		public void copy(FileRevision from, FileRevision to) {
 			System.out.printf("Got notified that %s(%s) was originally known as %s(%s)\n", to.getPath(), to.getRevision(), from.getPath(), from.getRevision());
 		}
-
-		public void next(HgChangeset changeset) {
-			final String s = print(changeset);
-			if (reverseOrder) {
-				// XXX in fact, need to insert s into l according to changeset.getRevision()
-				// because when file history is being followed, revisions of the original file (with smaller revNumber)
-				// are reported *after* revisions of present file and with addFirst appear above them
-				l.addFirst(s);
-			} else {
-				System.out.print(s);
-			}
-		}
-		
-		public void complete() {
-			if (!reverseOrder) {
-				return;
-			}
-			for (String s : l) {
-				System.out.print(s);
-			}
-			l.clear();
-//			changelogWalker = null;
-		}
-
-		private String print(HgChangeset cset) {
-			StringBuilder sb = new StringBuilder();
-			Formatter f = new Formatter(sb);
-			final Nodeid csetNodeid = cset.getNodeid();
-			f.format("changeset:   %d:%s\n", cset.getRevision(), complete ? csetNodeid : csetNodeid.shortNotation());
-			if (cset.getRevision() == tip || repo.getTags().isTagged(csetNodeid)) {
-				
-				sb.append("tag:         ");
-				for (String t : repo.getTags().tags(csetNodeid)) {
-					sb.append(t);
-					sb.append(' ');
-				}
-				if (cset.getRevision() == tip) {
-					sb.append("tip");
-				}
-				sb.append('\n');
-			}
-			if (complete) {
-//				if (changelogWalker == null) {
-//					changelogWalker = repo.getChangelog().new ParentWalker();
-//					changelogWalker.init();
-//				}
-//				Nodeid p1 = changelogWalker.safeFirstParent(csetNodeid);
-//				Nodeid p2 = changelogWalker.safeSecondParent(csetNodeid);
-				Nodeid p1 = cset.getFirstParentRevision();
-				Nodeid p2 = cset.getSecondParentRevision();
-				int p1x = p1 == Nodeid.NULL ? -1 : repo.getChangelog().getLocalRevision(p1);
-				int p2x = p2 == Nodeid.NULL ? -1 : repo.getChangelog().getLocalRevision(p2);
-				int mx = repo.getManifest().getLocalRevision(cset.getManifestRevision());
-				f.format("parent:      %d:%s\nparent:      %d:%s\nmanifest:    %d:%s\n", p1x, p1, p2x, p2, mx, cset.getManifestRevision());
-			}
-			f.format("user:        %s\ndate:        %s\n", cset.getUser(), cset.getDate());
-			if (!complete && verbose) {
-				final List<Path> files = cset.getAffectedFiles();
-				sb.append("files:      ");
-				for (Path s : files) {
-					sb.append(' ');
-					sb.append(s);
-				}
-				sb.append('\n');
-			}
-			if (complete) {
-				if (!cset.getModifiedFiles().isEmpty()) {
-					sb.append("files:      ");
-					for (FileRevision s : cset.getModifiedFiles()) {
-						sb.append(' ');
-						sb.append(s.getPath());
-					}
-					sb.append('\n');
-				}
-				if (!cset.getAddedFiles().isEmpty()) {
-					sb.append("files+:     ");
-					for (FileRevision s : cset.getAddedFiles()) {
-						sb.append(' ');
-						sb.append(s.getPath());
-					}
-					sb.append('\n');
-				}
-				if (!cset.getRemovedFiles().isEmpty()) {
-					sb.append("files-:     ");
-					for (Path s : cset.getRemovedFiles()) {
-						sb.append(' ');
-						sb.append(s);
-					}
-					sb.append('\n');
-				}
-//				if (cset.extras() != null) {
-//					sb.append("extra:      ");
-//					for (Map.Entry<String, String> e : cset.extras().entrySet()) {
-//						sb.append(' ');
-//						sb.append(e.getKey());
-//						sb.append('=');
-//						sb.append(e.getValue());
-//					}
-//					sb.append('\n');
-//				}
-			}
-			if (complete || verbose) {
-				f.format("description:\n%s\n\n", cset.getComment());
-			} else {
-				f.format("summary:     %s\n\n", cset.getComment());
-			}
-			return sb.toString();
-		}
 	}
 }
--- a/cmdline/org/tmatesoft/hg/console/Outgoing.java	Thu Apr 28 02:00:42 2011 +0200
+++ b/cmdline/org/tmatesoft/hg/console/Outgoing.java	Thu Apr 28 02:47:44 2011 +0200
@@ -19,18 +19,15 @@
 import java.util.Collection;
 import java.util.List;
 
+import org.tmatesoft.hg.core.HgOutgoingCommand;
+import org.tmatesoft.hg.core.HgRepoFacade;
 import org.tmatesoft.hg.core.Nodeid;
-import org.tmatesoft.hg.internal.RepositoryComparator;
-import org.tmatesoft.hg.repo.HgChangelog;
-import org.tmatesoft.hg.repo.HgChangelog.RawChangeset;
 import org.tmatesoft.hg.repo.HgLookup;
 import org.tmatesoft.hg.repo.HgRemoteRepository;
-import org.tmatesoft.hg.repo.HgRepository;
 
 
 /**
- * WORK IN PROGRESS, DO NOT USE
- * hg outgoing
+ * <em>hg outgoing</em>
  * 
  * @author Artem Tikhomirov
  * @author TMate Software Ltd.
@@ -38,60 +35,50 @@
 public class Outgoing {
 
 	public static void main(String[] args) throws Exception {
-		final boolean debug = true; // perhaps, use hg4j.remote.debug or own property?
 		Options cmdLineOpts = Options.parse(args);
-		HgRepository hgRepo = cmdLineOpts.findRepository();
-		if (hgRepo.isInvalid()) {
-			System.err.printf("Can't find repository in: %s\n", hgRepo.getLocation());
+		HgRepoFacade hgRepo = new HgRepoFacade();
+		if (!hgRepo.init(cmdLineOpts.findRepository())) {
+			System.err.printf("Can't find repository in: %s\n", hgRepo.getRepository().getLocation());
 			return;
 		}
-		HgRemoteRepository hgRemote = new HgLookup().detectRemote(cmdLineOpts.getSingle(""), hgRepo);
+		// XXX perhaps, HgRepoFacade shall get detectRemote() analog (to get remote server with respect of facade's repo)
+		HgRemoteRepository hgRemote = new HgLookup().detectRemote(cmdLineOpts.getSingle(""), hgRepo.getRepository());
 		if (hgRemote.isInvalid()) {
 			System.err.printf("Remote repository %s is not valid", hgRemote.getLocation());
 			return;
 		}
-
-		HgChangelog changelog = hgRepo.getChangelog();
-		HgChangelog.ParentWalker pw = changelog.new ParentWalker();
-		pw.init();
+		//
+		HgOutgoingCommand cmd = hgRepo.createOutgoingCommand();
+		cmd.against(hgRemote);
 		
-		RepositoryComparator repoCompare = new RepositoryComparator(pw, hgRemote);
-		repoCompare.compare(null);
-		if (debug) {
-			List<Nodeid> commonKnown = repoCompare.getCommon();
-			dump("Nodes known to be both locally and at remote server", commonKnown);
-		}
 		// find all local children of commonKnown
-		List<Nodeid> result = repoCompare.getLocalOnlyRevisions();
+		List<Nodeid> result = cmd.executeLite(null);
 		dump("Lite", result);
 		//
 		//
 		System.out.println("Full");
 		// show all, starting from next to common 
-		repoCompare.visitLocalOnlyRevisions(new HgChangelog.Inspector() {
-			private final ChangesetFormatter formatter = new ChangesetFormatter();
-			
-			public void next(int revisionNumber, Nodeid nodeid, RawChangeset cset) {
-				System.out.println(formatter.simple(revisionNumber, nodeid, cset));
-			}
-		});
+		final ChangesetDumpHandler h = new ChangesetDumpHandler(hgRepo.getRepository());
+		h.complete(cmdLineOpts.getBoolean("--debug")).verbose(cmdLineOpts.getBoolean("-v", "--verbose"));
+		cmd.executeFull(h);
+		h.done();
 	}
 
-	public static class ChangesetFormatter {
-		private final StringBuilder sb = new StringBuilder(1024);
-
-		public CharSequence simple(int revisionNumber, Nodeid nodeid, RawChangeset cset) {
-			sb.setLength(0);
-			sb.append(String.format("changeset:  %d:%s\n", revisionNumber, nodeid.toString()));
-			sb.append(String.format("user:       %s\n", cset.user()));
-			sb.append(String.format("date:       %s\n", cset.dateString()));
-			sb.append(String.format("comment:    %s\n\n", cset.comment()));
-			return sb;
-		}
-	}
+//	public static class ChangesetFormatter {
+//		private final StringBuilder sb = new StringBuilder(1024);
+//
+//		public CharSequence simple(int revisionNumber, Nodeid nodeid, RawChangeset cset) {
+//			sb.setLength(0);
+//			sb.append(String.format("changeset:  %d:%s\n", revisionNumber, nodeid.toString()));
+//			sb.append(String.format("user:       %s\n", cset.user()));
+//			sb.append(String.format("date:       %s\n", cset.dateString()));
+//			sb.append(String.format("comment:    %s\n\n", cset.comment()));
+//			return sb;
+//		}
+//	}
 	
 
-	private static void dump(String s, Collection<Nodeid> c) {
+	static void dump(String s, Collection<Nodeid> c) {
 		System.out.println(s);
 		for (Nodeid n : c) {
 			System.out.println(n);
--- a/src/org/tmatesoft/hg/core/HgOutgoingCommand.java	Thu Apr 28 02:00:42 2011 +0200
+++ b/src/org/tmatesoft/hg/core/HgOutgoingCommand.java	Thu Apr 28 02:47:44 2011 +0200
@@ -36,6 +36,7 @@
 
 	private final HgRepository localRepo;
 	private HgRemoteRepository remoteRepo;
+	@SuppressWarnings("unused")
 	private boolean includeSubrepo;
 	private RepositoryComparator comparator;
 	private HgChangelog.ParentWalker parentHelper;
--- a/src/org/tmatesoft/hg/internal/RepositoryComparator.java	Thu Apr 28 02:00:42 2011 +0200
+++ b/src/org/tmatesoft/hg/internal/RepositoryComparator.java	Thu Apr 28 02:47:44 2011 +0200
@@ -47,6 +47,7 @@
  */
 public class RepositoryComparator {
 
+	private final boolean debug = Boolean.parseBoolean(System.getProperty("hg4j.remote.debug"));
 	private final HgChangelog.ParentWalker localRepo;
 	private final HgRemoteRepository remoteRepo;
 	private List<Nodeid> common;
@@ -305,6 +306,12 @@
 				throw new HgBadStateException(String.format("Can't narrow down branch [%s, %s]", rb.head.shortNotation(), rb.root.shortNotation()));
 			}
 		}
+		if (debug) {
+			for (BranchChain bc : branches2load) {
+				System.out.println("calculateMissingBranches:");
+				bc.dump();
+			}
+		}
 		return branches2load;
 	}
 
@@ -343,7 +350,7 @@
 			return String.format("BranchChain [%s, %s]", branchRoot, branchHead);
 		}
 
-		public void dump() {
+		void dump() {
 			System.out.println(toString());
 			internalDump("  ");
 		}