6 # Copyright 2005 Matt Mackall <mpm@selenic.com> |
6 # Copyright 2005 Matt Mackall <mpm@selenic.com> |
7 # |
7 # |
8 # This software may be used and distributed according to the terms |
8 # This software may be used and distributed according to the terms |
9 # of the GNU General Public License, incorporated herein by reference. |
9 # of the GNU General Public License, incorporated herein by reference. |
10 |
10 |
11 import zlib, struct, sha, os, tempfile, binascii |
11 import zlib, struct, sha, os, tempfile, binascii, heapq |
12 from mercurial import mdiff |
12 from mercurial import mdiff |
13 |
13 |
14 def hex(node): return binascii.hexlify(node) |
14 def hex(node): return binascii.hexlify(node) |
15 def bin(node): return binascii.unhexlify(node) |
15 def bin(node): return binascii.unhexlify(node) |
16 def short(node): return hex(node[:4]) |
16 def short(node): return hex(node[:4]) |
274 |
274 |
275 self.cache = (node, n, text) |
275 self.cache = (node, n, text) |
276 return node |
276 return node |
277 |
277 |
278 def ancestor(self, a, b): |
278 def ancestor(self, a, b): |
279 def expand(list, map): |
279 # calculate the distance of every node from root |
280 a = [] |
280 dist = {nullid: 0} |
281 while list: |
281 for i in xrange(self.count()): |
282 n = list.pop(0) |
282 n = self.node(i) |
283 map[n] = 1 |
283 p1, p2 = self.parents(n) |
284 yield n |
284 dist[n] = max(dist[p1], dist[p2]) + 1 |
285 for p in self.parents(n): |
285 |
286 if p != nullid and p not in map: |
286 # traverse ancestors in order of decreasing distance from root |
287 list.append(p) |
287 def ancestors(node): |
288 yield nullid |
288 # we store negative distances because heap returns smallest member |
289 |
289 h = [(-dist[node], node)] |
290 amap = {} |
290 seen = {} |
291 bmap = {} |
291 earliest = self.count() |
292 ag = expand([a], amap) |
292 while h: |
293 bg = expand([b], bmap) |
293 d, n = heapq.heappop(h) |
294 adone = bdone = 0 |
294 r = self.rev(n) |
295 |
295 if n not in seen: |
296 while not adone or not bdone: |
296 seen[n] = 1 |
297 if not adone: |
297 yield (-d, n) |
298 an = ag.next() |
298 for p in self.parents(n): |
299 if an == nullid: |
299 heapq.heappush(h, (-dist[p], p)) |
300 adone = 1 |
300 |
301 elif an in bmap: |
301 x = ancestors(a) |
302 return an |
302 y = ancestors(b) |
303 if not bdone: |
303 lx = x.next() |
304 bn = bg.next() |
304 ly = y.next() |
305 if bn == nullid: |
305 |
306 bdone = 1 |
306 # increment each ancestor list until it is closer to root than |
307 elif bn in amap: |
307 # the other, or they match |
308 return bn |
308 while 1: |
309 |
309 if lx == ly: |
310 return nullid |
310 return lx[1] |
|
311 elif lx < ly: |
|
312 ly = y.next() |
|
313 elif lx > ly: |
|
314 lx = x.next() |
311 |
315 |
312 def group(self, linkmap): |
316 def group(self, linkmap): |
313 # given a list of changeset revs, return a set of deltas and |
317 # given a list of changeset revs, return a set of deltas and |
314 # metadata corresponding to nodes. the first delta is |
318 # metadata corresponding to nodes. the first delta is |
315 # parent(nodes[0]) -> nodes[0] the receiver is guaranteed to |
319 # parent(nodes[0]) -> nodes[0] the receiver is guaranteed to |