diff cmdline/org/tmatesoft/hg/console/Outgoing.java @ 181:cd3371670f0b

Refactor incoming and outgoing code to be shared with RepositoryComparator. Placeholders for in/out commands. Refactor common remote lookup code
author Artem Tikhomirov <tikhomirov.artem@gmail.com>
date Tue, 12 Apr 2011 19:10:38 +0200
parents 62665d8f0686
children c6fa4dbfc458
line wrap: on
line diff
--- a/cmdline/org/tmatesoft/hg/console/Outgoing.java	Wed Apr 06 03:08:05 2011 +0200
+++ b/cmdline/org/tmatesoft/hg/console/Outgoing.java	Tue Apr 12 19:10:38 2011 +0200
@@ -16,23 +16,15 @@
  */
 package org.tmatesoft.hg.console;
 
-import static org.tmatesoft.hg.core.Nodeid.NULL;
-
-import java.io.File;
-import java.net.URL;
 import java.util.Collection;
-import java.util.Collections;
-import java.util.LinkedList;
 import java.util.List;
 
 import org.tmatesoft.hg.core.HgException;
 import org.tmatesoft.hg.core.Nodeid;
-import org.tmatesoft.hg.internal.ConfigFile;
-import org.tmatesoft.hg.internal.Internals;
+import org.tmatesoft.hg.internal.RepositoryComparator;
 import org.tmatesoft.hg.repo.HgChangelog;
 import org.tmatesoft.hg.repo.HgLookup;
 import org.tmatesoft.hg.repo.HgRemoteRepository;
-import org.tmatesoft.hg.repo.HgRemoteRepository.RemoteBranch;
 import org.tmatesoft.hg.repo.HgRepository;
 
 
@@ -52,19 +44,18 @@
 			System.err.printf("Can't find repository in: %s\n", hgRepo.getLocation());
 			return;
 		}
-		String key = "hg4j-gc";
-		ConfigFile cfg = new Internals().newConfigFile();
-		cfg.addLocation(new File(System.getProperty("user.home"), ".hgrc"));
-		String server = cfg.getSection("paths").get(key);
-		if (server == null) {
-			throw new HgException(String.format("Can't find server %s specification in the config", key));
+		HgRemoteRepository hgRemote = new HgLookup().detectRemote("hg4j-gc", hgRepo);
+		if (hgRemote.isInvalid()) {
+			System.err.printf("Remote repository %s is not valid", hgRemote.getLocation());
+			return;
 		}
-		HgRemoteRepository hgRemote = new HgLookup().detect(new URL(server));
 
 		HgChangelog.ParentWalker pw = hgRepo.getChangelog().new ParentWalker();
 		pw.init();
 		
-		List<Nodeid> commonKnown = findCommonWithRemote(pw, hgRemote);
+		RepositoryComparator repoCompare = new RepositoryComparator(pw, hgRemote);
+		repoCompare.compare(null);
+		List<Nodeid> commonKnown = repoCompare.getCommon();
 		dump("Nodes known to be both locally and at remote server", commonKnown);
 		// sanity check
 		for (Nodeid n : commonKnown) {
@@ -77,86 +68,6 @@
 		dump("Result", result);
 	}
 	
-	private static List<Nodeid> findCommonWithRemote(HgChangelog.ParentWalker pwLocal, HgRemoteRepository hgRemote) throws HgException {
-		List<Nodeid> remoteHeads = hgRemote.heads();
-		LinkedList<Nodeid> common = new LinkedList<Nodeid>(); // these remotes are known in local
-		LinkedList<Nodeid> toQuery = new LinkedList<Nodeid>(); // these need further queries to find common
-		for (Nodeid rh : remoteHeads) {
-			if (pwLocal.knownNode(rh)) {
-				common.add(rh);
-			} else {
-				toQuery.add(rh);
-			}
-		}
-		if (toQuery.isEmpty()) {
-			return common; 
-		}
-		LinkedList<RemoteBranch> checkUp2Head = new LinkedList<RemoteBranch>(); // branch.root and branch.head are of interest only.
-		// these are branches with unknown head but known root, which might not be the last common known,
-		// i.e. there might be children changeset that are also available at remote, [..?..common-head..remote-head] - need to 
-		// scroll up to common head.
-		while (!toQuery.isEmpty()) {
-			List<RemoteBranch> remoteBranches = hgRemote.branches(toQuery);	//head, root, first parent, second parent
-			toQuery.clear();
-			while(!remoteBranches.isEmpty()) {
-				RemoteBranch rb = remoteBranches.remove(0);
-				// I assume branches remote call gives branches with head equal to what I pass there, i.e.
-				// that I don't need to check whether rb.head is unknown.
-				if (pwLocal.knownNode(rb.root)) {
-					// we known branch start, common head is somewhere in its descendants line  
-					checkUp2Head.add(rb);
-				} else {
-					// dig deeper in the history, if necessary
-					if (!NULL.equals(rb.p1) && !pwLocal.knownNode(rb.p1)) {
-						toQuery.add(rb.p1);
-					}
-					if (!NULL.equals(rb.p2) && !pwLocal.knownNode(rb.p2)) {
-						toQuery.add(rb.p2);
-					}
-				}
-			}
-		}
-		// can't check nodes between checkUp2Head element and local heads, remote might have distinct descendants sequence
-		for (RemoteBranch rb : checkUp2Head) {
-			// rb.root is known locally
-			List<Nodeid> remoteRevisions = hgRemote.between(rb.head, rb.root);
-			if (remoteRevisions.isEmpty()) {
-				// head is immediate child
-				common.add(rb.root);
-			} else {
-				// between gives result from head to root, I'd like to go in reverse direction
-				Collections.reverse(remoteRevisions);
-				Nodeid root = rb.root;
-				while(!remoteRevisions.isEmpty()) {
-					Nodeid n = remoteRevisions.remove(0);
-					if (pwLocal.knownNode(n)) {
-						if (remoteRevisions.isEmpty()) {
-							// this is the last known node before an unknown
-							common.add(n);
-							break;
-						}
-						if (remoteRevisions.size() == 1) {
-							// there's only one left between known n and unknown head
-							// this check is to save extra between query, not really essential
-							Nodeid last = remoteRevisions.remove(0);
-							common.add(pwLocal.knownNode(last) ? last : n);
-							break;
-						}
-						// might get handy for next between query, to narrow search down
-						root = n;
-					} else {
-						remoteRevisions = hgRemote.between(n, root);
-						Collections.reverse(remoteRevisions);
-						if (remoteRevisions.isEmpty()) {
-							common.add(root);
-						}
-					}
-				}
-			}
-		}
-		// TODO ensure unique elements in the list
-		return common;
-	}
 
 	private static void dump(String s, Collection<Nodeid> c) {
 		System.out.println(s);