##// END OF EJS Templates
Merge with stable
Merge with stable

File last commit:

r14494:1ffeeb91 default
r17331:ef8d612b merge default
Show More
ancestor.py
91 lines | 2.6 KiB | text/x-python | PythonLexer
Matt Mackall
Abstract ancestor algorithm into generic function...
r3135 # ancestor.py - generic DAG ancestor algorithm for mercurial
#
# Copyright 2006 Matt Mackall <mpm@selenic.com>
#
Martin Geisler
updated license to be explicit about GPL version 2
r8225 # This software may be used and distributed according to the terms of the
Matt Mackall
Update license to GPLv2+
r10263 # GNU General Public License version 2 or any later version.
Matt Mackall
Abstract ancestor algorithm into generic function...
r3135
import heapq
def ancestor(a, b, pfunc):
"""
Matt Mackall
ancestor: improve description
r13554 Returns the common ancestor of a and b that is furthest from a
root (as measured by longest path) or None if no ancestor is
found. If there are multiple common ancestors at the same
distance, the first one found is returned.
Matt Mackall
Abstract ancestor algorithm into generic function...
r3135
Sune Foldager
ancestor: improve docstring...
r9915 pfunc must return a list of parent vertices for a given vertex
Matt Mackall
Abstract ancestor algorithm into generic function...
r3135 """
if a == b:
return a
Matt Mackall
merge: sort arguments to stabilize the ancestor search
r11418 a, b = sorted([a, b])
Matt Mackall
Abstract ancestor algorithm into generic function...
r3135 # find depth from root of all ancestors
Matt Mackall
ancestor: improve description
r13554 # depth is stored as a negative for heapq
Nicolas Dumazet
ancestor: caching the parent list to improve performance...
r7882 parentcache = {}
Matt Mackall
Abstract ancestor algorithm into generic function...
r3135 visit = [a, b]
depth = {}
while visit:
vertex = visit[-1]
pl = pfunc(vertex)
Nicolas Dumazet
ancestor: caching the parent list to improve performance...
r7882 parentcache[vertex] = pl
Matt Mackall
Abstract ancestor algorithm into generic function...
r3135 if not pl:
depth[vertex] = 0
visit.pop()
else:
for p in pl:
Matt Mackall
backout most of 4f8067c94729
r12401 if p == a or p == b: # did we find a or b as a parent?
Matt Mackall
Abstract ancestor algorithm into generic function...
r3135 return p # we're done
if p not in depth:
visit.append(p)
if visit[-1] == vertex:
Matt Mackall
ancestor: improve description
r13554 # -(maximum distance of parents + 1)
Matt Mackall
Abstract ancestor algorithm into generic function...
r3135 depth[vertex] = min([depth[p] for p in pl]) - 1
visit.pop()
# traverse ancestors in order of decreasing distance from root
def ancestors(vertex):
h = [(depth[vertex], vertex)]
Benoit Boissinot
ancestor: use set instead of dict
r8465 seen = set()
Matt Mackall
Abstract ancestor algorithm into generic function...
r3135 while h:
d, n = heapq.heappop(h)
if n not in seen:
Benoit Boissinot
ancestor: use set instead of dict
r8465 seen.add(n)
Matt Mackall
Abstract ancestor algorithm into generic function...
r3135 yield (d, n)
Nicolas Dumazet
ancestor: caching the parent list to improve performance...
r7882 for p in parentcache[n]:
Matt Mackall
Abstract ancestor algorithm into generic function...
r3135 heapq.heappush(h, (depth[p], p))
def generations(vertex):
Benoit Boissinot
ancestor: use set instead of dict
r8465 sg, s = None, set()
Thomas Arendsen Hein
white space and line break cleanups
r3673 for g, v in ancestors(vertex):
Matt Mackall
Abstract ancestor algorithm into generic function...
r3135 if g != sg:
if sg:
yield sg, s
Benoit Boissinot
ancestor: use set instead of dict
r8465 sg, s = g, set((v,))
Matt Mackall
Abstract ancestor algorithm into generic function...
r3135 else:
Benoit Boissinot
ancestor: use set instead of dict
r8465 s.add(v)
Matt Mackall
Abstract ancestor algorithm into generic function...
r3135 yield sg, s
x = generations(a)
y = generations(b)
gx = x.next()
gy = y.next()
# increment each ancestor list until it is closer to root than
# the other, or they match
try:
Martin Geisler
check-code: flag 0/1 used as constant Boolean expression
r14494 while True:
Matt Mackall
Abstract ancestor algorithm into generic function...
r3135 if gx[0] == gy[0]:
for v in gx[1]:
if v in gy[1]:
return v
gy = y.next()
gx = x.next()
elif gx[0] > gy[0]:
gy = y.next()
else:
gx = x.next()
except StopIteration:
return None