mercurial/changegroup.py
changeset 39231 b41d023a412a
parent 39230 b518d495a560
child 39233 8b9b93bf70b1
equal deleted inserted replaced
39230:b518d495a560 39231:b41d023a412a
    29     match as matchmod,
    29     match as matchmod,
    30     mdiff,
    30     mdiff,
    31     phases,
    31     phases,
    32     pycompat,
    32     pycompat,
    33     repository,
    33     repository,
    34     revlog,
       
    35     util,
    34     util,
    36 )
    35 )
    37 
    36 
    38 from .utils import (
    37 from .utils import (
    39     interfaceutil,
    38     interfaceutil,
   510     p1node = attr.ib()
   509     p1node = attr.ib()
   511     p2node = attr.ib()
   510     p2node = attr.ib()
   512     basenode = attr.ib()
   511     basenode = attr.ib()
   513     ellipsis = attr.ib(default=False)
   512     ellipsis = attr.ib(default=False)
   514 
   513 
   515 @interfaceutil.implementer(repository.irevisiondelta)
       
   516 @attr.s(slots=True, frozen=True)
       
   517 class revisiondelta(object):
       
   518     node = attr.ib()
       
   519     p1node = attr.ib()
       
   520     p2node = attr.ib()
       
   521     basenode = attr.ib()
       
   522     linknode = attr.ib()
       
   523     flags = attr.ib()
       
   524     baserevisionsize = attr.ib()
       
   525     revision = attr.ib()
       
   526     delta = attr.ib()
       
   527 
       
   528 def _revisiondeltatochunks(delta, headerfn):
   514 def _revisiondeltatochunks(delta, headerfn):
   529     """Serialize a revisiondelta to changegroup chunks."""
   515     """Serialize a revisiondelta to changegroup chunks."""
   530 
   516 
   531     # The captured revision delta may be encoded as a delta against
   517     # The captured revision delta may be encoded as a delta against
   532     # a base revision or as a full revision. The changegroup format
   518     # a base revision or as a full revision. The changegroup format
   580     # order that they're introduced in dramatis personae by the
   566     # order that they're introduced in dramatis personae by the
   581     # changelog, so what we do is we sort the non-changelog histories
   567     # changelog, so what we do is we sort the non-changelog histories
   582     # by the order in which they are used by the changelog.
   568     # by the order in which they are used by the changelog.
   583     key = lambda n: cl.rev(lookup(n))
   569     key = lambda n: cl.rev(lookup(n))
   584     return [store.rev(n) for n in sorted(nodes, key=key)]
   570     return [store.rev(n) for n in sorted(nodes, key=key)]
   585 
       
   586 def _handlerevisiondeltarequest(store, request, prevnode):
       
   587     """Obtain a revisiondelta from a revisiondeltarequest"""
       
   588 
       
   589     node = request.node
       
   590     rev = store.rev(node)
       
   591 
       
   592     # Requesting a full revision.
       
   593     if request.basenode == nullid:
       
   594         baserev = nullrev
       
   595     # Requesting an explicit revision.
       
   596     elif request.basenode is not None:
       
   597         baserev = store.rev(request.basenode)
       
   598     # Allowing us to choose.
       
   599     else:
       
   600         p1, p2 = store.parentrevs(rev)
       
   601         dp = store.deltaparent(rev)
       
   602 
       
   603         if dp == nullrev and store.storedeltachains:
       
   604             # Avoid sending full revisions when delta parent is null. Pick prev
       
   605             # in that case. It's tempting to pick p1 in this case, as p1 will
       
   606             # be smaller in the common case. However, computing a delta against
       
   607             # p1 may require resolving the raw text of p1, which could be
       
   608             # expensive. The revlog caches should have prev cached, meaning
       
   609             # less CPU for changegroup generation. There is likely room to add
       
   610             # a flag and/or config option to control this behavior.
       
   611             baserev = store.rev(prevnode)
       
   612         elif dp == nullrev:
       
   613             # revlog is configured to use full snapshot for a reason,
       
   614             # stick to full snapshot.
       
   615             baserev = nullrev
       
   616         elif dp not in (p1, p2, store.rev(prevnode)):
       
   617             # Pick prev when we can't be sure remote has the base revision.
       
   618             baserev = store.rev(prevnode)
       
   619         else:
       
   620             baserev = dp
       
   621 
       
   622         if baserev != nullrev and not store.candelta(baserev, rev):
       
   623             baserev = nullrev
       
   624 
       
   625     revision = None
       
   626     delta = None
       
   627     baserevisionsize = None
       
   628 
       
   629     if store.iscensored(baserev) or store.iscensored(rev):
       
   630         try:
       
   631             revision = store.revision(node, raw=True)
       
   632         except error.CensoredNodeError as e:
       
   633             revision = e.tombstone
       
   634 
       
   635         if baserev != nullrev:
       
   636             baserevisionsize = store.rawsize(baserev)
       
   637 
       
   638     elif baserev == nullrev:
       
   639         revision = store.revision(node, raw=True)
       
   640     else:
       
   641         delta = store.revdiff(baserev, rev)
       
   642 
       
   643     extraflags = revlog.REVIDX_ELLIPSIS if request.ellipsis else 0
       
   644 
       
   645     return revisiondelta(
       
   646         node=node,
       
   647         p1node=request.p1node,
       
   648         p2node=request.p2node,
       
   649         linknode=request.linknode,
       
   650         basenode=store.node(baserev),
       
   651         flags=store.flags(rev) | extraflags,
       
   652         baserevisionsize=baserevisionsize,
       
   653         revision=revision,
       
   654         delta=delta,
       
   655     )
       
   656 
   571 
   657 def _makenarrowdeltarequest(cl, store, ischangelog, rev, node, linkrev,
   572 def _makenarrowdeltarequest(cl, store, ischangelog, rev, node, linkrev,
   658                             linknode, clrevtolocalrev, fullclnodes,
   573                             linknode, clrevtolocalrev, fullclnodes,
   659                             precomputedellipsis):
   574                             precomputedellipsis):
   660     linkparents = precomputedellipsis[linkrev]
   575     linkparents = precomputedellipsis[linkrev]
   830     progress = None
   745     progress = None
   831     if units is not None:
   746     if units is not None:
   832         progress = repo.ui.makeprogress(_('bundling'), unit=units,
   747         progress = repo.ui.makeprogress(_('bundling'), unit=units,
   833                                         total=len(requests))
   748                                         total=len(requests))
   834 
   749 
   835     prevnode = store.node(revs[0])
   750     for i, delta in enumerate(store.emitrevisiondeltas(requests)):
   836     for i, request in enumerate(requests):
       
   837         if progress:
   751         if progress:
   838             progress.update(i + 1)
   752             progress.update(i + 1)
   839 
   753 
   840         delta = _handlerevisiondeltarequest(store, request, prevnode)
       
   841 
       
   842         yield delta
   754         yield delta
   843 
       
   844         prevnode = request.node
       
   845 
   755 
   846     if progress:
   756     if progress:
   847         progress.complete()
   757         progress.complete()
   848 
   758 
   849 class cgpacker(object):
   759 class cgpacker(object):