Mercurial > hg > mercurial-crew-with-dirclash
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 |