comparison hgext3rd/topic/stack.py @ 2919:5b514ab2ab4e

stack: properly order stack when gaps existing inside it We transitively search for the next "stack" ancestors, of changeset in the stack not based on other revision of the stack. This should help having a consistent display when topic are interleaved.
author Pierre-Yves David <pierre-yves.david@octobus.net>
date Sat, 09 Sep 2017 22:32:50 +0530
parents 0437158e0ed6
children 3a9303b7b648
comparison
equal deleted inserted replaced
2918:0437158e0ed6 2919:5b514ab2ab4e
6 from mercurial import ( 6 from mercurial import (
7 destutil, 7 destutil,
8 context, 8 context,
9 error, 9 error,
10 node, 10 node,
11 phases,
11 util, 12 util,
12 ) 13 )
13 from .evolvebits import builddependencies, _orderrevs, _singlesuccessor 14 from .evolvebits import builddependencies, _singlesuccessor
14 15
15 short = node.short 16 short = node.short
16 17
17 # TODO: compat 18 # TODO: compat
18 19
48 def index(self, item): 49 def index(self, item):
49 return self.revs.index(item) 50 return self.revs.index(item)
50 51
51 @util.propertycache 52 @util.propertycache
52 def _dependencies(self): 53 def _dependencies(self):
53 return builddependencies(self._repo, self.revs[1:]) 54 deps, rdeps = builddependencies(self._repo, self._revs)
55
56 repo = self._repo
57 srcpfunc = repo.changelog.parentrevs
58
59 ### post process to skip over possible gaps in the stack
60 #
61 # For example in the following situation, we need to detect that "t3"
62 # indirectly depends on t2.
63 #
64 # o t3
65 # |
66 # o other
67 # |
68 # o t2
69 # |
70 # o t1
71
72 pmap = {}
73
74 def pfuncrev(repo, rev):
75 """a special "parent func" that also consider successors"""
76 parents = pmap.get(rev)
77 if parents is None:
78 parents = [repo[_singlesuccessor(repo, repo[p])].rev()
79 for p in srcpfunc(rev) if 0 <= p]
80 pmap[rev] = parents
81 return parents
82
83 revs = self._revs
84 stackrevs = set(self._revs)
85 for root in [r for r in revs if not deps[r]]:
86 seen = set()
87 stack = [root]
88 while stack:
89 current = stack.pop()
90 for p in pfuncrev(repo, current):
91 if p in seen:
92 continue
93 seen.add(p)
94 if p in stackrevs:
95 rdeps[p].add(root)
96 deps[root].add(p)
97 elif phases.public < repo[p].phase():
98 # traverse only if we did not found a proper candidate
99 stack.append(p)
100
101 return deps, rdeps
54 102
55 @util.propertycache 103 @util.propertycache
56 def revs(self): 104 def revs(self):
57 revs = _orderrevs(self._repo, self._revs) 105 # some duplication/change from _orderrevs because we use a post
106 # processed dependency graph.
107
108 # Step 1: compute relation of revision with each other
109 dependencies, rdependencies = self._dependencies
110 dependencies = dependencies.copy()
111 rdependencies = rdependencies.copy()
112 # Step 2: Build the ordering
113 # Remove the revisions with no dependency(A) and add them to the ordering.
114 # Removing these revisions leads to new revisions with no dependency (the
115 # one depending on A) that we can remove from the dependency graph and add
116 # to the ordering. We progress in a similar fashion until the ordering is
117 # built
118 solvablerevs = [r for r in sorted(dependencies.keys())
119 if not dependencies[r]]
120 revs = []
121 while solvablerevs:
122 rev = solvablerevs.pop()
123 for dependent in rdependencies[rev]:
124 dependencies[dependent].remove(rev)
125 if not dependencies[dependent]:
126 solvablerevs.append(dependent)
127 del dependencies[rev]
128 revs.append(rev)
129
130 revs.extend(sorted(dependencies))
131 # step 3: add t0
58 if revs: 132 if revs:
59 pt1 = self._repo[revs[0]].p1() 133 pt1 = self._repo[revs[0]].p1()
60 if pt1.obsolete(): 134 if pt1.obsolete():
61 pt1 = self._repo[_singlesuccessor(self._repo, pt1)] 135 pt1 = self._repo[_singlesuccessor(self._repo, pt1)]
62 revs.insert(0, pt1.rev()) 136 revs.insert(0, pt1.rev())