1442 cl = self.changelog |
1442 cl = self.changelog |
1443 mf = self.manifest |
1443 mf = self.manifest |
1444 mfs = {} # needed manifests |
1444 mfs = {} # needed manifests |
1445 fnodes = {} # needed file nodes |
1445 fnodes = {} # needed file nodes |
1446 |
1446 |
1447 # Compute the list of changesets in this changegroup. |
|
1448 # Some bases may turn out to be superfluous, and some heads may be |
|
1449 # too. nodesbetween will return the minimal set of bases and heads |
|
1450 # necessary to re-create the changegroup. |
|
1451 if not bases: |
1447 if not bases: |
1452 bases = [nullid] |
1448 bases = [nullid] |
1453 csets, bases, heads = cl.nodesbetween(bases, heads) |
1449 csets, bases, heads = cl.nodesbetween(bases, heads) |
1454 |
1450 |
1455 # can we go through the fast path ? |
1451 # can we go through the fast path ? |
1456 heads.sort() |
1452 heads.sort() |
1457 allheads = self.heads() |
1453 if heads == sorted(self.heads()): |
1458 allheads.sort() |
|
1459 if heads == allheads: |
|
1460 return self._changegroup(csets, source) |
1454 return self._changegroup(csets, source) |
1461 |
1455 |
1462 # slow path |
1456 # slow path |
1463 self.hook('preoutgoing', throw=True, source=source) |
1457 self.hook('preoutgoing', throw=True, source=source) |
1464 self.changegroupinfo(csets, source) |
1458 self.changegroupinfo(csets, source) |
1465 |
1459 |
1466 # We assume that all ancestors of bases are known |
1460 # We assume that all ancestors of bases are known |
1467 commonrevs = set(cl.ancestors(*[cl.rev(n) for n in bases])) |
1461 commonrevs = set(cl.ancestors(*[cl.rev(n) for n in bases])) |
1468 |
|
1469 # A changeset always belongs to itself, so the changenode lookup |
|
1470 # function for a changenode is identity. |
|
1471 def identity(x): |
|
1472 return x |
|
1473 |
1462 |
1474 # A function generating function that sets up the initial environment |
1463 # A function generating function that sets up the initial environment |
1475 # the inner function. |
1464 # the inner function. |
1476 def filenode_collector(changedfiles): |
1465 def filenode_collector(changedfiles): |
1477 # This gathers information from each manifestnode included in the |
1466 # This gathers information from each manifestnode included in the |
1479 # so we can include those in the changegroup too. |
1468 # so we can include those in the changegroup too. |
1480 # |
1469 # |
1481 # It also remembers which changenode each filenode belongs to. It |
1470 # It also remembers which changenode each filenode belongs to. It |
1482 # does this by assuming the a filenode belongs to the changenode |
1471 # does this by assuming the a filenode belongs to the changenode |
1483 # the first manifest that references it belongs to. |
1472 # the first manifest that references it belongs to. |
1484 def collect(mannode): |
1473 def collect(mnode): |
1485 r = mf.rev(mannode) |
1474 r = mf.rev(mnode) |
1486 if mf.deltaparent(r) in mf.parentrevs(r): |
1475 if mf.deltaparent(r) in mf.parentrevs(r): |
1487 # If the previous rev is one of the parents, |
1476 # If the previous rev is one of the parents, |
1488 # we only need to see a diff. |
1477 # we only need to see a diff. |
1489 deltamf = mf.readdelta(mannode) |
1478 deltamf = mf.readdelta(mnode) |
1490 # For each line in the delta |
1479 # For each line in the delta |
1491 for f, fnode in deltamf.iteritems(): |
1480 for f, fnode in deltamf.iteritems(): |
1492 # And if the file is in the list of files we care |
1481 # And if the file is in the list of files we care |
1493 # about. |
1482 # about. |
1494 if f in changedfiles: |
1483 if f in changedfiles: |
1495 # Get the changenode this manifest belongs to |
1484 # Get the changenode this manifest belongs to |
1496 clnode = mfs[mannode] |
1485 clnode = mfs[mnode] |
1497 # Create the set of filenodes for the file if |
1486 # Create the set of filenodes for the file if |
1498 # there isn't one already. |
1487 # there isn't one already. |
1499 ndset = fnodes.setdefault(f, {}) |
1488 ndset = fnodes.setdefault(f, {}) |
1500 # And set the filenode's changelog node to the |
1489 # And set the filenode's changelog node to the |
1501 # manifest's if it hasn't been set already. |
1490 # manifest's if it hasn't been set already. |
1502 ndset.setdefault(fnode, clnode) |
1491 ndset.setdefault(fnode, clnode) |
1503 else: |
1492 else: |
1504 # Otherwise we need a full manifest. |
1493 # Otherwise we need a full manifest. |
1505 m = mf.read(mannode) |
1494 m = mf.read(mnode) |
1506 # For every file in we care about. |
1495 # For every file in we care about. |
1507 for f in changedfiles: |
1496 for f in changedfiles: |
1508 fnode = m.get(f, None) |
1497 fnode = m.get(f, None) |
1509 # If it's in the manifest |
1498 # If it's in the manifest |
1510 if fnode is not None: |
1499 if fnode is not None: |
1511 # See comments above. |
1500 # See comments above. |
1512 clnode = mfs[mannode] |
1501 clnode = mfs[mnode] |
1513 ndset = fnodes.setdefault(f, {}) |
1502 ndset = fnodes.setdefault(f, {}) |
1514 ndset.setdefault(fnode, clnode) |
1503 ndset.setdefault(fnode, clnode) |
1515 return collect |
1504 return collect |
1516 |
1505 |
1517 # If we determine that a particular file or manifest node must be a |
1506 # If we determine that a particular file or manifest node must be a |
1539 changedfiles = set() |
1528 changedfiles = set() |
1540 collect = changegroup.collector(cl, mfs, changedfiles) |
1529 collect = changegroup.collector(cl, mfs, changedfiles) |
1541 |
1530 |
1542 # Create a changenode group generator that will call our functions |
1531 # Create a changenode group generator that will call our functions |
1543 # back to lookup the owning changenode and collect information. |
1532 # back to lookup the owning changenode and collect information. |
1544 group = cl.group(csets, identity, collect) |
1533 group = cl.group(csets, lambda x: x, collect) |
1545 for cnt, chnk in enumerate(group): |
1534 for cnt, chnk in enumerate(group): |
1546 yield chnk |
1535 yield chnk |
1547 # revlog.group yields three entries per node, so |
1536 # revlog.group yields three entries per node, so |
1548 # dividing by 3 gives an approximation of how many |
1537 # dividing by 3 gives an approximation of how many |
1549 # nodes have been processed. |
1538 # nodes have been processed. |
1584 # If any filenodes are left, generate the group for them, |
1573 # If any filenodes are left, generate the group for them, |
1585 # otherwise don't bother. |
1574 # otherwise don't bother. |
1586 if missingfnodes: |
1575 if missingfnodes: |
1587 yield changegroup.chunkheader(len(fname)) |
1576 yield changegroup.chunkheader(len(fname)) |
1588 yield fname |
1577 yield fname |
1589 # Sort the filenodes by their revision # (topological order) |
|
1590 nodeiter = list(missingfnodes) |
|
1591 nodeiter.sort(key=filerevlog.rev) |
|
1592 # Create a group generator and only pass in a changenode |
1578 # Create a group generator and only pass in a changenode |
1593 # lookup function as we need to collect no information |
1579 # lookup function as we need to collect no information |
1594 # from filenodes. |
1580 # from filenodes. |
1595 group = filerevlog.group(nodeiter, |
1581 group = filerevlog.group( |
1596 lambda fnode: missingfnodes[fnode]) |
1582 sorted(missingfnodes, key=filerevlog.rev), |
|
1583 lambda fnode: missingfnodes[fnode]) |
1597 for chnk in group: |
1584 for chnk in group: |
1598 # even though we print the same progress on |
1585 # even though we print the same progress on |
1599 # most loop iterations, put the progress call |
1586 # most loop iterations, put the progress call |
1600 # here so that time estimates (if any) can be updated |
1587 # here so that time estimates (if any) can be updated |
1601 self.ui.progress( |
1588 self.ui.progress( |