mercurial/exchange.py
changeset 51577 b5d494f7d28a
parent 50699 2aaabd8f4471
child 51581 e0194b3ea312
equal deleted inserted replaced
51576:de5bf3fe0233 51577:b5d494f7d28a
   343         """future remote heads if the changeset push fails"""
   343         """future remote heads if the changeset push fails"""
   344         if self.revs is None:
   344         if self.revs is None:
   345             # not target to push, all common are relevant
   345             # not target to push, all common are relevant
   346             return self.outgoing.commonheads
   346             return self.outgoing.commonheads
   347         unfi = self.repo.unfiltered()
   347         unfi = self.repo.unfiltered()
   348         # I want cheads = heads(::ancestorsof and ::commonheads)
   348         # I want cheads = heads(::push_heads and ::commonheads)
   349         # (ancestorsof is revs with secret changeset filtered out)
       
   350         #
   349         #
   351         # This can be expressed as:
   350         # To push, we already computed
   352         #     cheads = ( (ancestorsof and ::commonheads)
   351         #     common = (::commonheads)
   353         #              + (commonheads and ::ancestorsof))"
   352         #     missing = ((commonheads::push_heads) - commonheads)
   354         #              )
       
   355         #
   353         #
   356         # while trying to push we already computed the following:
   354         # So we basically search
   357         #     common = (::commonheads)
       
   358         #     missing = ((commonheads::ancestorsof) - commonheads)
       
   359         #
   355         #
   360         # We can pick:
   356         #     almost_heads = heads((parents(missing) + push_heads) & common)
   361         # * ancestorsof part of common (::commonheads)
   357         #
       
   358         # We use "almost" here as this can return revision that are ancestors
       
   359         # of other in the set and we need to explicitly turn it into an
       
   360         # antichain later. We can do so using:
       
   361         #
       
   362         #     cheads = heads(almost_heads::almost_heads)
       
   363         #
       
   364         # In pratice the code is a bit more convulted to avoid some extra
       
   365         # computation. It aims at doing the same computation as highlighted
       
   366         # above however.
   362         common = self.outgoing.common
   367         common = self.outgoing.common
   363         rev = self.repo.changelog.index.rev
   368         unfi = self.repo.unfiltered()
   364         cheads = [node for node in self.revs if rev(node) in common]
   369         cl = unfi.changelog
   365         # and
   370         to_rev = cl.index.rev
   366         # * commonheads parents on missing
   371         to_node = cl.node
   367         revset = unfi.set(
   372         parent_revs = cl.parentrevs
   368             b'%ln and parents(roots(%ln))',
   373         unselected = []
   369             self.outgoing.commonheads,
   374         cheads = set()
   370             self.outgoing.missing,
   375         # XXX-perf: `self.revs` and `outgoing.missing` could hold revs directly
   371         )
   376         for n in self.revs:
   372         cheads.extend(c.node() for c in revset)
   377             r = to_rev(n)
   373         return cheads
   378             if r in common:
       
   379                 cheads.add(r)
       
   380             else:
       
   381                 unselected.append(r)
       
   382         known_non_heads = cl.ancestors(cheads, inclusive=True)
       
   383         if unselected:
       
   384             missing_revs = {to_rev(n) for n in self.outgoing.missing}
       
   385             missing_revs.add(nullrev)
       
   386             root_points = set()
       
   387             for r in missing_revs:
       
   388                 p1, p2 = parent_revs(r)
       
   389                 if p1 not in missing_revs and p1 not in known_non_heads:
       
   390                     root_points.add(p1)
       
   391                 if p2 not in missing_revs and p2 not in known_non_heads:
       
   392                     root_points.add(p2)
       
   393             if root_points:
       
   394                 heads = unfi.revs('heads(%ld::%ld)', root_points, root_points)
       
   395                 cheads.update(heads)
       
   396         # XXX-perf: could this be a set of revision?
       
   397         return [to_node(r) for r in sorted(cheads)]
   374 
   398 
   375     @property
   399     @property
   376     def commonheads(self):
   400     def commonheads(self):
   377         """set of all common heads after changeset bundle push"""
   401         """set of all common heads after changeset bundle push"""
   378         if self.cgresult:
   402         if self.cgresult: