Mercurial > hg4j
diff src/org/tmatesoft/hg/core/HgIncomingCommand.java @ 192:e5407b5a586a
Incoming and Outgoing commands are alive
author | Artem Tikhomirov <tikhomirov.artem@gmail.com> |
---|---|
date | Fri, 15 Apr 2011 03:17:03 +0200 |
parents | cd3371670f0b |
children | 344e8d7e4d6e |
line wrap: on
line diff
--- a/src/org/tmatesoft/hg/core/HgIncomingCommand.java Thu Apr 14 19:53:31 2011 +0200 +++ b/src/org/tmatesoft/hg/core/HgIncomingCommand.java Fri Apr 15 03:17:03 2011 +0200 @@ -16,26 +16,50 @@ */ package org.tmatesoft.hg.core; +import java.io.IOException; +import java.util.ArrayList; +import java.util.LinkedHashSet; +import java.util.LinkedList; import java.util.List; +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.HgRemoteRepository; import org.tmatesoft.hg.repo.HgRepository; import org.tmatesoft.hg.util.CancelledException; /** - * + * Command to find out changes available in a remote repository, missing locally. + * * @author Artem Tikhomirov * @author TMate Software Ltd. */ public class HgIncomingCommand { - private final HgRepository repo; + private final HgRepository localRepo; + private HgRemoteRepository remoteRepo; private boolean includeSubrepo; + private RepositoryComparator comparator; + private List<BranchChain> missingBranches; + private HgChangelog.ParentWalker parentHelper; public HgIncomingCommand(HgRepository hgRepo) { - repo = hgRepo; + localRepo = hgRepo; + } + + public HgIncomingCommand against(HgRemoteRepository hgRemote) { + remoteRepo = hgRemote; + comparator = null; + missingBranches = null; + return this; } /** + * PLACEHOLDER, NOT IMPLEMENTED YET. + * * Select specific branch to pull * @return <code>this</code> for convenience */ @@ -44,6 +68,8 @@ } /** + * PLACEHOLDER, NOT IMPLEMENTED YET. + * * Whether to include sub-repositories when collecting changes, default is <code>true</code> XXX or false? * @return <code>this</code> for convenience */ @@ -61,7 +87,16 @@ * @throws CancelledException */ public List<Nodeid> executeLite(Object context) throws HgException, CancelledException { - throw HgRepository.notImplemented(); + LinkedHashSet<Nodeid> result = new LinkedHashSet<Nodeid>(); + RepositoryComparator repoCompare = getComparator(context); + for (BranchChain bc : getMissingBranches(context)) { + List<Nodeid> missing = repoCompare.visitBranches(bc); + assert bc.branchRoot.equals(missing.get(0)); + missing.remove(0); + result.addAll(missing); + } + ArrayList<Nodeid> rv = new ArrayList<Nodeid>(result); + return rv; } /** @@ -70,7 +105,74 @@ * @throws HgException * @throws CancelledException */ - public void executeFull(HgLogCommand.Handler handler) throws HgException, CancelledException { - throw HgRepository.notImplemented(); + public void executeFull(final HgLogCommand.Handler handler) throws HgException, CancelledException { + if (handler == null) { + throw new IllegalArgumentException("Delegate can't be null"); + } + final List<Nodeid> common = getCommon(handler); + HgBundle changegroup = remoteRepo.getChanges(new LinkedList<Nodeid>(common)); + try { + changegroup.changes(localRepo, new HgChangelog.Inspector() { + private int localIndex; + private final HgChangelog.ParentWalker parentHelper; + private final ChangesetTransformer transformer; + private final HgChangelog changelog; + + { + transformer = new ChangesetTransformer(localRepo, handler); + parentHelper = getParentHelper(); + changelog = localRepo.getChangelog(); + } + + public void next(int revisionNumber, Nodeid nodeid, RawChangeset cset) { + if (parentHelper.knownNode(nodeid)) { + if (!common.contains(nodeid)) { + throw new HgBadStateException("Bundle shall not report known nodes other than roots we've supplied"); + } + localIndex = changelog.getLocalRevision(nodeid); + return; + } + transformer.next(++localIndex, nodeid, cset); + } + }); + } catch (IOException ex) { + throw new HgException(ex); + } + } + + private RepositoryComparator getComparator(Object context) throws HgException, CancelledException { + if (remoteRepo == null) { + throw new HgBadArgumentException("Shall specify remote repository to compare against", null); + } + if (comparator == null) { + comparator = new RepositoryComparator(getParentHelper(), remoteRepo); + comparator.compare(context); + } + return comparator; + } + + private HgChangelog.ParentWalker getParentHelper() { + if (parentHelper == null) { + parentHelper = localRepo.getChangelog().new ParentWalker(); + parentHelper.init(); + } + return parentHelper; + } + + private List<BranchChain> getMissingBranches(Object context) throws HgException, CancelledException { + if (missingBranches == null) { + missingBranches = getComparator(context).calculateMissingBranches(); + } + return missingBranches; + } + + private List<Nodeid> getCommon(Object context) throws HgException, CancelledException { + 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 : getMissingBranches(context)) { + common.add(bc.branchRoot); + } + return new LinkedList<Nodeid>(common); } }