mercurial/localrepo.py
changeset 13707 296e78744d32
parent 13706 7beb9834d185
child 13708 ce9b3043b79d
equal deleted inserted replaced
13706:7beb9834d185 13707:296e78744d32
  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(