comparison src/org/tmatesoft/hg/internal/RepositoryComparator.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 ec1820f64d2b
children 706bcc7cfee4
comparison
equal deleted inserted replaced
191:b777502a06f5 192:e5407b5a586a
16 */ 16 */
17 package org.tmatesoft.hg.internal; 17 package org.tmatesoft.hg.internal;
18 18
19 import static org.tmatesoft.hg.core.Nodeid.NULL; 19 import static org.tmatesoft.hg.core.Nodeid.NULL;
20 20
21 import java.util.ArrayList;
21 import java.util.Collections; 22 import java.util.Collections;
22 import java.util.HashMap; 23 import java.util.HashMap;
23 import java.util.HashSet; 24 import java.util.HashSet;
24 import java.util.LinkedList; 25 import java.util.LinkedList;
25 import java.util.List; 26 import java.util.List;
27 import java.util.ListIterator;
26 import java.util.Map; 28 import java.util.Map;
27 import java.util.Map.Entry; 29 import java.util.Map.Entry;
28 30
29 import org.tmatesoft.hg.core.HgBadStateException; 31 import org.tmatesoft.hg.core.HgBadStateException;
30 import org.tmatesoft.hg.core.HgException; 32 import org.tmatesoft.hg.core.HgException;
57 ProgressSupport progressSupport = ProgressSupport.Factory.get(context); 59 ProgressSupport progressSupport = ProgressSupport.Factory.get(context);
58 CancelSupport cancelSupport = CancelSupport.Factory.get(context); 60 CancelSupport cancelSupport = CancelSupport.Factory.get(context);
59 cancelSupport.checkCancelled(); 61 cancelSupport.checkCancelled();
60 progressSupport.start(10); 62 progressSupport.start(10);
61 common = Collections.unmodifiableList(findCommonWithRemote()); 63 common = Collections.unmodifiableList(findCommonWithRemote());
64 // sanity check
65 for (Nodeid n : common) {
66 if (!localRepo.knownNode(n)) {
67 throw new HgBadStateException("Unknown node reported as common:" + n);
68 }
69 }
62 progressSupport.done(); 70 progressSupport.done();
63 return this; 71 return this;
64 } 72 }
65 73
66 public List<Nodeid> getCommon() { 74 public List<Nodeid> getCommon() {
67 if (common == null) { 75 if (common == null) {
68 throw new HgBadStateException("Call #compare(Object) first"); 76 throw new HgBadStateException("Call #compare(Object) first");
69 } 77 }
70 return common; 78 return common;
79 }
80
81 /**
82 * @return revisions that are children of common entries, i.e. revisions that are present on the local server and not on remote.
83 */
84 public List<Nodeid> getLocalOnlyRevisions() {
85 return localRepo.childrenOf(getCommon());
86 }
87
88 /**
89 * Similar to @link {@link #getLocalOnlyRevisions()}, use this one if you need access to changelog entry content, not
90 * only its revision number.
91 * @param inspector delegate to analyze changesets, shall not be <code>null</code>
92 */
93 public void visitLocalOnlyRevisions(HgChangelog.Inspector inspector) {
94 if (inspector == null) {
95 throw new IllegalArgumentException();
96 }
97 // one can use localRepo.childrenOf(getCommon()) and then iterate over nodeids, but there seems to be
98 // another approach to get all changes after common:
99 // find index of earliest revision, and report all that were later
100 final HgChangelog changelog = localRepo.getRepo().getChangelog();
101 int earliestRevision = Integer.MAX_VALUE;
102 List<Nodeid> commonKnown = getCommon();
103 for (Nodeid n : commonKnown) {
104 if (!localRepo.hasChildren(n)) {
105 // there might be (old) nodes, known both locally and remotely, with no children
106 // hence, we don't need to consider their local revision number
107 continue;
108 }
109 int lr = changelog.getLocalRevision(n);
110 if (lr < earliestRevision) {
111 earliestRevision = lr;
112 }
113 }
114 if (earliestRevision < 0 || earliestRevision >= changelog.getLastRevision()) {
115 throw new HgBadStateException(String.format("Invalid index of common known revision: %d in total of %d", earliestRevision, 1+changelog.getLastRevision()));
116 }
117 changelog.range(earliestRevision+1, changelog.getLastRevision(), inspector);
71 } 118 }
72 119
73 private List<Nodeid> findCommonWithRemote() throws HgException { 120 private List<Nodeid> findCommonWithRemote() throws HgException {
74 List<Nodeid> remoteHeads = remoteRepo.heads(); 121 List<Nodeid> remoteHeads = remoteRepo.heads();
75 LinkedList<Nodeid> resultCommon = new LinkedList<Nodeid>(); // these remotes are known in local 122 LinkedList<Nodeid> resultCommon = new LinkedList<Nodeid>(); // these remotes are known in local
401 if (!resultOk) { 448 if (!resultOk) {
402 throw new HgBadStateException("See console for details"); // FIXME 449 throw new HgBadStateException("See console for details"); // FIXME
403 } 450 }
404 return fromRootToHead; 451 return fromRootToHead;
405 } 452 }
453
454 /**
455 * returns in order from branch root to head
456 * for a non-empty BranchChain, shall return modifiable list
457 */
458 public List<Nodeid> visitBranches(BranchChain bc) throws HgException {
459 if (bc == null) {
460 return Collections.emptyList();
461 }
462 List<Nodeid> mine = completeBranch(bc.branchRoot, bc.branchHead);
463 if (bc.isTerminal()) {
464 return mine;
465 }
466 List<Nodeid> parentBranch1 = visitBranches(bc.p1);
467 List<Nodeid> parentBranch2 = visitBranches(bc.p2);
468 // merge
469 LinkedList<Nodeid> merged = new LinkedList<Nodeid>();
470 ListIterator<Nodeid> i1 = parentBranch1.listIterator(), i2 = parentBranch2.listIterator();
471 while (i1.hasNext() && i2.hasNext()) {
472 Nodeid n1 = i1.next();
473 Nodeid n2 = i2.next();
474 if (n1.equals(n2)) {
475 merged.addLast(n1);
476 } else {
477 // first different => add both, and continue adding both tails sequentially
478 merged.add(n2);
479 merged.add(n1);
480 break;
481 }
482 }
483 // copy rest of second parent branch
484 while (i2.hasNext()) {
485 merged.add(i2.next());
486 }
487 // copy rest of first parent branch
488 while (i1.hasNext()) {
489 merged.add(i1.next());
490 }
491 //
492 ArrayList<Nodeid> rv = new ArrayList<Nodeid>(mine.size() + merged.size());
493 rv.addAll(merged);
494 rv.addAll(mine);
495 return rv;
496 }
497
406 } 498 }