# HG changeset patch # User Artem Tikhomirov # Date 1302714550 -7200 # Node ID ec1820f64d2be892a84d286bf1034b81e7e81abd # Parent 9807bf8f3a9c6194875080a3a8a31d3c978a6bfa Complete incoming cmdline client, with both lite (revisions) and complete (full changeset) information dump diff -r 9807bf8f3a9c -r ec1820f64d2b cmdline/org/tmatesoft/hg/console/Incoming.java --- a/cmdline/org/tmatesoft/hg/console/Incoming.java Wed Apr 13 14:15:13 2011 +0200 +++ b/cmdline/org/tmatesoft/hg/console/Incoming.java Wed Apr 13 19:09:10 2011 +0200 @@ -23,19 +23,23 @@ 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.ListIterator; import java.util.Map.Entry; +import org.tmatesoft.hg.core.HgBadStateException; import org.tmatesoft.hg.core.HgException; 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.HgLookup; import org.tmatesoft.hg.repo.HgRemoteRepository; import org.tmatesoft.hg.repo.HgRepository; +import org.tmatesoft.hg.repo.HgChangelog.RawChangeset; /** @@ -53,12 +57,12 @@ return; } Options cmdLineOpts = Options.parse(args); - HgRepository hgRepo = cmdLineOpts.findRepository(); + final HgRepository hgRepo = cmdLineOpts.findRepository(); if (hgRepo.isInvalid()) { System.err.printf("Can't find repository in: %s\n", hgRepo.getLocation()); return; } - HgRemoteRepository hgRemote = new HgLookup().detectRemote("svnkit", hgRepo); + HgRemoteRepository hgRemote = new HgLookup().detectRemote(cmdLineOpts.getSingle(""), hgRepo); if (hgRemote.isInvalid()) { System.err.printf("Remote repository %s is not valid", hgRemote.getLocation()); return; @@ -72,11 +76,17 @@ RepositoryComparator repoCompare = new RepositoryComparator(pw, hgRemote); repoCompare.compare(null); List missingBranches0 = repoCompare.calculateMissingBranches(); + final LinkedHashSet common = new LinkedHashSet(); + // 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 : missingBranches0) { bc.dump(); - + common.add(bc.branchRoot); // common known node List missing = visitBranches(repoCompare, bc); - // Collections.reverse(missing); // useful to test output, from newer to older + 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); @@ -86,10 +96,31 @@ } System.out.println("Branch done"); } - + // + // Complete + HgBundle changegroup = hgRemote.getChanges(new LinkedList(common)); + changegroup.changes(hgRepo, new HgChangelog.Inspector() { + private int localIndex; + + 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.printf("changeset: %d:%s\n", ++localIndex, nodeid.toString()); + System.out.printf("user: %s\n", cset.user()); + System.out.printf("date: %s\n", cset.dateString()); + System.out.printf("comment: %s\n\n", cset.comment()); + + } + }); } - + // returns in order from branch root to head + // for a non-empty BranchChain, shall return modifiable list private static List visitBranches(RepositoryComparator repoCompare, BranchChain bc) throws HgException { if (bc == null) { return Collections.emptyList(); diff -r 9807bf8f3a9c -r ec1820f64d2b src/org/tmatesoft/hg/internal/RepositoryComparator.java --- a/src/org/tmatesoft/hg/internal/RepositoryComparator.java Wed Apr 13 14:15:13 2011 +0200 +++ b/src/org/tmatesoft/hg/internal/RepositoryComparator.java Wed Apr 13 19:09:10 2011 +0200 @@ -181,6 +181,8 @@ chainElement = new BranchChain(rb.head); // record this unknown branch to download later branches2load.add(chainElement); + // the only chance we'll need chainElement in the head2chain is when we know this branch's root + head2chain.put(rb.head, chainElement); } if (localRepo.knownNode(rb.root)) { // we known branch start, common head is somewhere in its descendants line @@ -203,8 +205,9 @@ Nodeid h = rb.head; Nodeid r = rb.root; int watchdog = 1000; + assert head2chain.containsKey(h); BranchChain bc = head2chain.get(h); - assert bc != null; + assert bc != null : h.toString(); // if we know branch root locally, there could be no parent branch chain elements. assert bc.p1 == null; assert bc.p2 == null; diff -r 9807bf8f3a9c -r ec1820f64d2b src/org/tmatesoft/hg/repo/HgRemoteRepository.java --- a/src/org/tmatesoft/hg/repo/HgRemoteRepository.java Wed Apr 13 14:15:13 2011 +0200 +++ b/src/org/tmatesoft/hg/repo/HgRemoteRepository.java Wed Apr 13 19:09:10 2011 +0200 @@ -301,7 +301,8 @@ } } - // WireProtocol wiki: roots = a list of the latest nodes on every service side changeset branch that both the client and server know about. + // WireProtocol wiki: roots = a list of the latest nodes on every service side changeset branch that both the client and server know about. + // perhaps, shall be named 'changegroup' public HgBundle getChanges(List roots) throws HgException { StringBuilder sb = new StringBuilder(20 + roots.size() * 41); sb.append("roots="); @@ -385,6 +386,7 @@ end = to; } } + public static final class RemoteBranch { public final Nodeid head, root, p1, p2;