517 basenode = attr.ib() |
519 basenode = attr.ib() |
518 # 20 byte node of changeset revision this delta is associated with. |
520 # 20 byte node of changeset revision this delta is associated with. |
519 linknode = attr.ib() |
521 linknode = attr.ib() |
520 # 2 bytes of flags to apply to revision data. |
522 # 2 bytes of flags to apply to revision data. |
521 flags = attr.ib() |
523 flags = attr.ib() |
522 # Iterable of chunks holding raw delta data. |
524 # Size of base revision this delta is against. May be None if |
523 deltachunks = attr.ib() |
525 # basenode is nullid. |
|
526 baserevisionsize = attr.ib() |
|
527 # Raw fulltext revision data. |
|
528 revision = attr.ib() |
|
529 # Delta between the basenode and node. |
|
530 delta = attr.ib() |
524 |
531 |
525 def _revisiondeltatochunks(delta, headerfn): |
532 def _revisiondeltatochunks(delta, headerfn): |
526 """Serialize a revisiondelta to changegroup chunks.""" |
533 """Serialize a revisiondelta to changegroup chunks.""" |
|
534 |
|
535 # The captured revision delta may be encoded as a delta against |
|
536 # a base revision or as a full revision. The changegroup format |
|
537 # requires that everything on the wire be deltas. So for full |
|
538 # revisions, we need to invent a header that says to rewrite |
|
539 # data. |
|
540 |
|
541 if delta.delta is not None: |
|
542 prefix, data = b'', delta.delta |
|
543 elif delta.basenode == nullid: |
|
544 data = delta.revision |
|
545 prefix = mdiff.trivialdiffheader(len(data)) |
|
546 else: |
|
547 data = delta.revision |
|
548 prefix = mdiff.replacediffheader(delta.baserevisionsize, |
|
549 len(data)) |
|
550 |
527 meta = headerfn(delta) |
551 meta = headerfn(delta) |
528 l = len(meta) + sum(len(x) for x in delta.deltachunks) |
552 |
529 yield chunkheader(l) |
553 yield chunkheader(len(meta) + len(prefix) + len(data)) |
530 yield meta |
554 yield meta |
531 for x in delta.deltachunks: |
555 if prefix: |
532 yield x |
556 yield prefix |
|
557 yield data |
533 |
558 |
534 def _sortnodesnormal(store, nodes, reorder): |
559 def _sortnodesnormal(store, nodes, reorder): |
535 """Sort nodes for changegroup generation and turn into revnums.""" |
560 """Sort nodes for changegroup generation and turn into revnums.""" |
536 # for generaldelta revlogs, we linearize the revs; this will both be |
561 # for generaldelta revlogs, we linearize the revs; this will both be |
537 # much quicker and generate a much smaller bundle |
562 # much quicker and generate a much smaller bundle |
566 """Construct a revision delta for non-ellipses changegroup generation.""" |
591 """Construct a revision delta for non-ellipses changegroup generation.""" |
567 node = store.node(rev) |
592 node = store.node(rev) |
568 p1, p2 = store.parentrevs(rev) |
593 p1, p2 = store.parentrevs(rev) |
569 base = deltaparentfn(store, rev, p1, p2, prev) |
594 base = deltaparentfn(store, rev, p1, p2, prev) |
570 |
595 |
571 prefix = '' |
596 revision = None |
|
597 delta = None |
|
598 baserevisionsize = None |
|
599 |
572 if store.iscensored(base) or store.iscensored(rev): |
600 if store.iscensored(base) or store.iscensored(rev): |
573 try: |
601 try: |
574 delta = store.revision(node, raw=True) |
602 revision = store.revision(node, raw=True) |
575 except error.CensoredNodeError as e: |
603 except error.CensoredNodeError as e: |
576 delta = e.tombstone |
604 revision = e.tombstone |
577 if base == nullrev: |
605 |
578 prefix = mdiff.trivialdiffheader(len(delta)) |
606 if base != nullrev: |
579 else: |
607 baserevisionsize = store.rawsize(base) |
580 baselen = store.rawsize(base) |
608 |
581 prefix = mdiff.replacediffheader(baselen, len(delta)) |
|
582 elif base == nullrev: |
609 elif base == nullrev: |
583 delta = store.revision(node, raw=True) |
610 revision = store.revision(node, raw=True) |
584 prefix = mdiff.trivialdiffheader(len(delta)) |
|
585 else: |
611 else: |
586 delta = store.revdiff(base, rev) |
612 delta = store.revdiff(base, rev) |
|
613 |
587 p1n, p2n = store.parents(node) |
614 p1n, p2n = store.parents(node) |
588 |
615 |
589 return revisiondelta( |
616 return revisiondelta( |
590 node=node, |
617 node=node, |
591 p1node=p1n, |
618 p1node=p1n, |
592 p2node=p2n, |
619 p2node=p2n, |
593 basenode=store.node(base), |
620 basenode=store.node(base), |
594 linknode=linknode, |
621 linknode=linknode, |
595 flags=store.flags(rev), |
622 flags=store.flags(rev), |
596 deltachunks=(prefix, delta), |
623 baserevisionsize=baserevisionsize, |
|
624 revision=revision, |
|
625 delta=delta, |
597 ) |
626 ) |
598 |
627 |
599 def _revisiondeltanarrow(cl, store, ischangelog, rev, linkrev, |
628 def _revisiondeltanarrow(cl, store, ischangelog, rev, linkrev, |
600 linknode, clrevtolocalrev, fullclnodes, |
629 linknode, clrevtolocalrev, fullclnodes, |
601 precomputedellipsis): |
630 precomputedellipsis): |
675 p1n, p2n = store.node(p1), store.node(p2) |
704 p1n, p2n = store.node(p1), store.node(p2) |
676 flags = store.flags(rev) |
705 flags = store.flags(rev) |
677 flags |= revlog.REVIDX_ELLIPSIS |
706 flags |= revlog.REVIDX_ELLIPSIS |
678 |
707 |
679 # TODO: try and actually send deltas for ellipsis data blocks |
708 # TODO: try and actually send deltas for ellipsis data blocks |
680 data = store.revision(n) |
|
681 diffheader = mdiff.trivialdiffheader(len(data)) |
|
682 |
709 |
683 return revisiondelta( |
710 return revisiondelta( |
684 node=n, |
711 node=n, |
685 p1node=p1n, |
712 p1node=p1n, |
686 p2node=p2n, |
713 p2node=p2n, |
687 basenode=nullid, |
714 basenode=nullid, |
688 linknode=linknode, |
715 linknode=linknode, |
689 flags=flags, |
716 flags=flags, |
690 deltachunks=(diffheader, data), |
717 baserevisionsize=None, |
|
718 revision=store.revision(n), |
|
719 delta=None, |
691 ) |
720 ) |
692 |
721 |
693 def deltagroup(repo, revs, store, ischangelog, lookup, deltaparentfn, |
722 def deltagroup(repo, revs, store, ischangelog, lookup, deltaparentfn, |
694 units=None, |
723 units=None, |
695 ellipses=False, clrevtolocalrev=None, fullclnodes=None, |
724 ellipses=False, clrevtolocalrev=None, fullclnodes=None, |