mercurial/changegroup.py
changeset 39004 e11d07cc125c
parent 39003 58377518201c
child 39005 d56a6b78de3b
equal deleted inserted replaced
39003:58377518201c 39004:e11d07cc125c
   586         linknode=linknode,
   586         linknode=linknode,
   587         flags=store.flags(rev),
   587         flags=store.flags(rev),
   588         deltachunks=(prefix, delta),
   588         deltachunks=(prefix, delta),
   589     )
   589     )
   590 
   590 
       
   591 def _revisiondeltanarrow(cl, store, ischangelog, rev, linkrev,
       
   592                          linknode, clrevtolocalrev, fullclnodes,
       
   593                          precomputedellipsis):
       
   594     linkparents = precomputedellipsis[linkrev]
       
   595     def local(clrev):
       
   596         """Turn a changelog revnum into a local revnum.
       
   597 
       
   598         The ellipsis dag is stored as revnums on the changelog,
       
   599         but when we're producing ellipsis entries for
       
   600         non-changelog revlogs, we need to turn those numbers into
       
   601         something local. This does that for us, and during the
       
   602         changelog sending phase will also expand the stored
       
   603         mappings as needed.
       
   604         """
       
   605         if clrev == nullrev:
       
   606             return nullrev
       
   607 
       
   608         if ischangelog:
       
   609             return clrev
       
   610 
       
   611         # Walk the ellipsis-ized changelog breadth-first looking for a
       
   612         # change that has been linked from the current revlog.
       
   613         #
       
   614         # For a flat manifest revlog only a single step should be necessary
       
   615         # as all relevant changelog entries are relevant to the flat
       
   616         # manifest.
       
   617         #
       
   618         # For a filelog or tree manifest dirlog however not every changelog
       
   619         # entry will have been relevant, so we need to skip some changelog
       
   620         # nodes even after ellipsis-izing.
       
   621         walk = [clrev]
       
   622         while walk:
       
   623             p = walk[0]
       
   624             walk = walk[1:]
       
   625             if p in clrevtolocalrev:
       
   626                 return clrevtolocalrev[p]
       
   627             elif p in fullclnodes:
       
   628                 walk.extend([pp for pp in cl.parentrevs(p)
       
   629                                 if pp != nullrev])
       
   630             elif p in precomputedellipsis:
       
   631                 walk.extend([pp for pp in precomputedellipsis[p]
       
   632                                 if pp != nullrev])
       
   633             else:
       
   634                 # In this case, we've got an ellipsis with parents
       
   635                 # outside the current bundle (likely an
       
   636                 # incremental pull). We "know" that we can use the
       
   637                 # value of this same revlog at whatever revision
       
   638                 # is pointed to by linknode. "Know" is in scare
       
   639                 # quotes because I haven't done enough examination
       
   640                 # of edge cases to convince myself this is really
       
   641                 # a fact - it works for all the (admittedly
       
   642                 # thorough) cases in our testsuite, but I would be
       
   643                 # somewhat unsurprised to find a case in the wild
       
   644                 # where this breaks down a bit. That said, I don't
       
   645                 # know if it would hurt anything.
       
   646                 for i in pycompat.xrange(rev, 0, -1):
       
   647                     if store.linkrev(i) == clrev:
       
   648                         return i
       
   649                 # We failed to resolve a parent for this node, so
       
   650                 # we crash the changegroup construction.
       
   651                 raise error.Abort(
       
   652                     'unable to resolve parent while packing %r %r'
       
   653                     ' for changeset %r' % (store.indexfile, rev, clrev))
       
   654 
       
   655         return nullrev
       
   656 
       
   657     if not linkparents or (
       
   658         store.parentrevs(rev) == (nullrev, nullrev)):
       
   659         p1, p2 = nullrev, nullrev
       
   660     elif len(linkparents) == 1:
       
   661         p1, = sorted(local(p) for p in linkparents)
       
   662         p2 = nullrev
       
   663     else:
       
   664         p1, p2 = sorted(local(p) for p in linkparents)
       
   665 
       
   666     n = store.node(rev)
       
   667     p1n, p2n = store.node(p1), store.node(p2)
       
   668     flags = store.flags(rev)
       
   669     flags |= revlog.REVIDX_ELLIPSIS
       
   670 
       
   671     # TODO: try and actually send deltas for ellipsis data blocks
       
   672     data = store.revision(n)
       
   673     diffheader = mdiff.trivialdiffheader(len(data))
       
   674 
       
   675     return revisiondelta(
       
   676         node=n,
       
   677         p1node=p1n,
       
   678         p2node=p2n,
       
   679         basenode=nullid,
       
   680         linknode=linknode,
       
   681         flags=flags,
       
   682         deltachunks=(diffheader, data),
       
   683     )
       
   684 
   591 class cgpacker(object):
   685 class cgpacker(object):
   592     def __init__(self, repo, filematcher, version, allowreorder,
   686     def __init__(self, repo, filematcher, version, allowreorder,
   593                  deltaparentfn, builddeltaheader, manifestsend,
   687                  deltaparentfn, builddeltaheader, manifestsend,
   594                  bundlecaps=None, ellipses=False,
   688                  bundlecaps=None, ellipses=False,
   595                  shallow=False, ellipsisroots=None, fullnodes=None):
   689                  shallow=False, ellipsisroots=None, fullnodes=None):
   705                     delta = _revisiondeltanormal(store, curr, prev, linknode,
   799                     delta = _revisiondeltanormal(store, curr, prev, linknode,
   706                                                  self._deltaparentfn)
   800                                                  self._deltaparentfn)
   707                 elif linkrev not in self._precomputedellipsis:
   801                 elif linkrev not in self._precomputedellipsis:
   708                     delta = None
   802                     delta = None
   709                 else:
   803                 else:
   710                     delta = self._revisiondeltanarrow(
   804                     delta = _revisiondeltanarrow(
   711                         cl, store, ischangelog, curr, linkrev, linknode,
   805                         cl, store, ischangelog, curr, linkrev, linknode,
   712                         clrevtolocalrev, self._fullclnodes,
   806                         clrevtolocalrev, self._fullclnodes,
   713                         self._precomputedellipsis)
   807                         self._precomputedellipsis)
   714             else:
   808             else:
   715                 delta = _revisiondeltanormal(store, curr, prev, linknode,
   809                 delta = _revisiondeltanormal(store, curr, prev, linknode,
  1055                                         clrevtolocalrev=clrevtolocalrev):
  1149                                         clrevtolocalrev=clrevtolocalrev):
  1056                     size += len(chunk)
  1150                     size += len(chunk)
  1057                     yield chunk
  1151                     yield chunk
  1058                 self._verbosenote(_('%8.i  %s\n') % (size, fname))
  1152                 self._verbosenote(_('%8.i  %s\n') % (size, fname))
  1059         progress.complete()
  1153         progress.complete()
  1060 
       
  1061     def _revisiondeltanarrow(self, cl, store, ischangelog, rev, linkrev,
       
  1062                              linknode, clrevtolocalrev, fullclnodes,
       
  1063                              precomputedellipsis):
       
  1064         linkparents = precomputedellipsis[linkrev]
       
  1065         def local(clrev):
       
  1066             """Turn a changelog revnum into a local revnum.
       
  1067 
       
  1068             The ellipsis dag is stored as revnums on the changelog,
       
  1069             but when we're producing ellipsis entries for
       
  1070             non-changelog revlogs, we need to turn those numbers into
       
  1071             something local. This does that for us, and during the
       
  1072             changelog sending phase will also expand the stored
       
  1073             mappings as needed.
       
  1074             """
       
  1075             if clrev == nullrev:
       
  1076                 return nullrev
       
  1077 
       
  1078             if ischangelog:
       
  1079                 return clrev
       
  1080 
       
  1081             # Walk the ellipsis-ized changelog breadth-first looking for a
       
  1082             # change that has been linked from the current revlog.
       
  1083             #
       
  1084             # For a flat manifest revlog only a single step should be necessary
       
  1085             # as all relevant changelog entries are relevant to the flat
       
  1086             # manifest.
       
  1087             #
       
  1088             # For a filelog or tree manifest dirlog however not every changelog
       
  1089             # entry will have been relevant, so we need to skip some changelog
       
  1090             # nodes even after ellipsis-izing.
       
  1091             walk = [clrev]
       
  1092             while walk:
       
  1093                 p = walk[0]
       
  1094                 walk = walk[1:]
       
  1095                 if p in clrevtolocalrev:
       
  1096                     return clrevtolocalrev[p]
       
  1097                 elif p in fullclnodes:
       
  1098                     walk.extend([pp for pp in cl.parentrevs(p)
       
  1099                                     if pp != nullrev])
       
  1100                 elif p in precomputedellipsis:
       
  1101                     walk.extend([pp for pp in precomputedellipsis[p]
       
  1102                                     if pp != nullrev])
       
  1103                 else:
       
  1104                     # In this case, we've got an ellipsis with parents
       
  1105                     # outside the current bundle (likely an
       
  1106                     # incremental pull). We "know" that we can use the
       
  1107                     # value of this same revlog at whatever revision
       
  1108                     # is pointed to by linknode. "Know" is in scare
       
  1109                     # quotes because I haven't done enough examination
       
  1110                     # of edge cases to convince myself this is really
       
  1111                     # a fact - it works for all the (admittedly
       
  1112                     # thorough) cases in our testsuite, but I would be
       
  1113                     # somewhat unsurprised to find a case in the wild
       
  1114                     # where this breaks down a bit. That said, I don't
       
  1115                     # know if it would hurt anything.
       
  1116                     for i in pycompat.xrange(rev, 0, -1):
       
  1117                         if store.linkrev(i) == clrev:
       
  1118                             return i
       
  1119                     # We failed to resolve a parent for this node, so
       
  1120                     # we crash the changegroup construction.
       
  1121                     raise error.Abort(
       
  1122                         'unable to resolve parent while packing %r %r'
       
  1123                         ' for changeset %r' % (store.indexfile, rev, clrev))
       
  1124 
       
  1125             return nullrev
       
  1126 
       
  1127         if not linkparents or (
       
  1128             store.parentrevs(rev) == (nullrev, nullrev)):
       
  1129             p1, p2 = nullrev, nullrev
       
  1130         elif len(linkparents) == 1:
       
  1131             p1, = sorted(local(p) for p in linkparents)
       
  1132             p2 = nullrev
       
  1133         else:
       
  1134             p1, p2 = sorted(local(p) for p in linkparents)
       
  1135 
       
  1136         n = store.node(rev)
       
  1137         p1n, p2n = store.node(p1), store.node(p2)
       
  1138         flags = store.flags(rev)
       
  1139         flags |= revlog.REVIDX_ELLIPSIS
       
  1140 
       
  1141         # TODO: try and actually send deltas for ellipsis data blocks
       
  1142         data = store.revision(n)
       
  1143         diffheader = mdiff.trivialdiffheader(len(data))
       
  1144 
       
  1145         return revisiondelta(
       
  1146             node=n,
       
  1147             p1node=p1n,
       
  1148             p2node=p2n,
       
  1149             basenode=nullid,
       
  1150             linknode=linknode,
       
  1151             flags=flags,
       
  1152             deltachunks=(diffheader, data),
       
  1153         )
       
  1154 
  1154 
  1155 def _deltaparentprev(store, rev, p1, p2, prev):
  1155 def _deltaparentprev(store, rev, p1, p2, prev):
  1156     """Resolve a delta parent to the previous revision.
  1156     """Resolve a delta parent to the previous revision.
  1157 
  1157 
  1158     Used for version 1 changegroups, which don't support generaldelta.
  1158     Used for version 1 changegroups, which don't support generaldelta.