comparison mercurial/revlog.py @ 1469:0847c45ffee6

Merge bundle -r work from Eric Hopper
author Matt Mackall <mpm@selenic.com>
date Thu, 27 Oct 2005 12:26:16 -0700
parents bc3e66edb04c 26e73acc0cdf
children 1a216cb4ee64
comparison
equal deleted inserted replaced
1456:214f42f23a3b 1469:0847c45ffee6
247 if p not in reachable: 247 if p not in reachable:
248 reachable[p] = 1 248 reachable[p] = 1
249 visit.append(p) 249 visit.append(p)
250 return reachable 250 return reachable
251 251
252 def nodesbetween(self, roots=None, heads=None):
253 """Return a tuple containing three elements. Elements 1 and 2 contain
254 a final list bases and heads after all the unreachable ones have been
255 pruned. Element 0 contains a topologically sorted list of all
256
257 nodes that satisfy these constraints:
258 1. All nodes must be descended from a node in roots (the nodes on
259 roots are considered descended from themselves).
260 2. All nodes must also be ancestors of a node in heads (the nodes in
261 heads are considered to be their own ancestors).
262
263 If roots is unspecified, nullid is assumed as the only root.
264 If heads is unspecified, it is taken to be the output of the
265 heads method (i.e. a list of all nodes in the repository that
266 have no children)."""
267 nonodes = ([], [], [])
268 if roots is not None:
269 roots = list(roots)
270 if not roots:
271 return nonodes
272 lowestrev = min([self.rev(n) for n in roots])
273 else:
274 roots = [nullid] # Everybody's a descendent of nullid
275 lowestrev = -1
276 if (lowestrev == -1) and (heads is None):
277 # We want _all_ the nodes!
278 return ([self.node(r) for r in xrange(0, self.count())],
279 [nullid], list(self.heads()))
280 if heads is None:
281 # All nodes are ancestors, so the latest ancestor is the last
282 # node.
283 highestrev = self.count() - 1
284 # Set ancestors to None to signal that every node is an ancestor.
285 ancestors = None
286 # Set heads to an empty dictionary for later discovery of heads
287 heads = {}
288 else:
289 heads = list(heads)
290 if not heads:
291 return nonodes
292 ancestors = {}
293 # Start at the top and keep marking parents until we're done.
294 nodestotag = heads[:]
295 # Turn heads into a dictionary so we can remove 'fake' heads.
296 # Also, later we will be using it to filter out the heads we can't
297 # find from roots.
298 heads = dict.fromkeys(heads, 0)
299 # Remember where the top was so we can use it as a limit later.
300 highestrev = max([self.rev(n) for n in nodestotag])
301 while nodestotag:
302 # grab a node to tag
303 n = nodestotag.pop()
304 # Never tag nullid
305 if n == nullid:
306 continue
307 # A node's revision number represents its place in a
308 # topologically sorted list of nodes.
309 r = self.rev(n)
310 if r >= lowestrev:
311 if n not in ancestors:
312 # If we are possibly a descendent of one of the roots
313 # and we haven't already been marked as an ancestor
314 ancestors[n] = 1 # Mark as ancestor
315 # Add non-nullid parents to list of nodes to tag.
316 nodestotag.extend([p for p in self.parents(n) if
317 p != nullid])
318 elif n in heads: # We've seen it before, is it a fake head?
319 # So it is, real heads should not be the ancestors of
320 # any other heads.
321 heads.pop(n)
322 if not ancestors:
323 return nonodes
324 # Now that we have our set of ancestors, we want to remove any
325 # roots that are not ancestors.
326
327 # If one of the roots was nullid, everything is included anyway.
328 if lowestrev > -1:
329 # But, since we weren't, let's recompute the lowest rev to not
330 # include roots that aren't ancestors.
331
332 # Filter out roots that aren't ancestors of heads
333 roots = [n for n in roots if n in ancestors]
334 # Recompute the lowest revision
335 if roots:
336 lowestrev = min([self.rev(n) for n in roots])
337 else:
338 # No more roots? Return empty list
339 return nonodes
340 else:
341 # We are descending from nullid, and don't need to care about
342 # any other roots.
343 lowestrev = -1
344 roots = [nullid]
345 # Transform our roots list into a 'set' (i.e. a dictionary where the
346 # values don't matter.
347 descendents = dict.fromkeys(roots, 1)
348 # Also, keep the original roots so we can filter out roots that aren't
349 # 'real' roots (i.e. are descended from other roots).
350 roots = descendents.copy()
351 # Our topologically sorted list of output nodes.
352 orderedout = []
353 # Don't start at nullid since we don't want nullid in our output list,
354 # and if nullid shows up in descedents, empty parents will look like
355 # they're descendents.
356 for r in xrange(max(lowestrev, 0), highestrev + 1):
357 n = self.node(r)
358 isdescendent = False
359 if lowestrev == -1: # Everybody is a descendent of nullid
360 isdescendent = True
361 elif n in descendents:
362 # n is already a descendent
363 isdescendent = True
364 # This check only needs to be done here because all the roots
365 # will start being marked is descendents before the loop.
366 if n in roots:
367 # If n was a root, check if it's a 'real' root.
368 p = tuple(self.parents(n))
369 # If any of its parents are descendents, it's not a root.
370 if (p[0] in descendents) or (p[1] in descendents):
371 roots.pop(n)
372 else:
373 p = tuple(self.parents(n))
374 # A node is a descendent if either of its parents are
375 # descendents. (We seeded the dependents list with the roots
376 # up there, remember?)
377 if (p[0] in descendents) or (p[1] in descendents):
378 descendents[n] = 1
379 isdescendent = True
380 if isdescendent and ((ancestors is None) or (n in ancestors)):
381 # Only include nodes that are both descendents and ancestors.
382 orderedout.append(n)
383 if (ancestors is not None) and (n in heads):
384 # We're trying to figure out which heads are reachable
385 # from roots.
386 # Mark this head as having been reached
387 heads[n] = 1
388 elif ancestors is None:
389 # Otherwise, we're trying to discover the heads.
390 # Assume this is a head because if it isn't, the next step
391 # will eventually remove it.
392 heads[n] = 1
393 # But, obviously its parents aren't.
394 for p in self.parents(n):
395 heads.pop(p, None)
396 heads = [n for n in heads.iterkeys() if heads[n] != 0]
397 roots = roots.keys()
398 assert orderedout
399 assert roots
400 assert heads
401 return (orderedout, roots, heads)
402
252 def heads(self, stop=None): 403 def heads(self, stop=None):
253 """return the list of all nodes that have no children""" 404 """return the list of all nodes that have no children"""
254 p = {} 405 p = {}
255 h = [] 406 h = []
256 stoprev = 0 407 stoprev = 0
480 gy = y.next() 631 gy = y.next()
481 else: 632 else:
482 #print "next x" 633 #print "next x"
483 gx = x.next() 634 gx = x.next()
484 635
485 def group(self, linkmap): 636 def group(self, nodelist, lookup, infocollect = None):
486 """calculate a delta group 637 """calculate a delta group
487 638
488 Given a list of changeset revs, return a set of deltas and 639 Given a list of changeset revs, return a set of deltas and
489 metadata corresponding to nodes. the first delta is 640 metadata corresponding to nodes. the first delta is
490 parent(nodes[0]) -> nodes[0] the receiver is guaranteed to 641 parent(nodes[0]) -> nodes[0] the receiver is guaranteed to
491 have this parent as it has all history before these 642 have this parent as it has all history before these
492 changesets. parent is parent[0] 643 changesets. parent is parent[0]
493 """ 644 """
494 revs = [] 645 revs = [self.rev(n) for n in nodelist]
495 needed = {} 646 needed = dict.fromkeys(revs, 1)
496
497 # find file nodes/revs that match changeset revs
498 for i in xrange(0, self.count()):
499 if self.index[i][3] in linkmap:
500 revs.append(i)
501 needed[i] = 1
502 647
503 # if we don't have any revisions touched by these changesets, bail 648 # if we don't have any revisions touched by these changesets, bail
504 if not revs: 649 if not revs:
505 yield struct.pack(">l", 0) 650 yield struct.pack(">l", 0)
506 return 651 return
564 deltas = [] 709 deltas = []
565 for d in xrange(0, len(revs) - 1): 710 for d in xrange(0, len(revs) - 1):
566 a, b = revs[d], revs[d + 1] 711 a, b = revs[d], revs[d + 1]
567 n = self.node(b) 712 n = self.node(b)
568 713
714 if infocollect is not None:
715 infocollect(n)
716
569 # do we need to construct a new delta? 717 # do we need to construct a new delta?
570 if a + 1 != b or self.base(b) == b: 718 if a + 1 != b or self.base(b) == b:
571 if a >= 0: 719 if a >= 0:
572 base = self.base(a) 720 base = self.base(a)
573 ta = chunks[self.base(a)] 721 ta = chunks[self.base(a)]
585 d = self.diff(ta, tb) 733 d = self.diff(ta, tb)
586 else: 734 else:
587 d = chunks[b] 735 d = chunks[b]
588 736
589 p = self.parents(n) 737 p = self.parents(n)
590 meta = n + p[0] + p[1] + linkmap[self.linkrev(n)] 738 meta = n + p[0] + p[1] + lookup(n)
591 l = struct.pack(">l", len(meta) + len(d) + 4) 739 l = struct.pack(">l", len(meta) + len(d) + 4)
592 yield l 740 yield l
593 yield meta 741 yield meta
594 yield d 742 yield d
595 743