equal
deleted
inserted
replaced
151 import os |
151 import os |
152 import re |
152 import re |
153 import string |
153 import string |
154 import struct |
154 import struct |
155 import sys |
155 import sys |
|
156 import typing |
156 |
157 |
157 from .i18n import _ |
158 from .i18n import _ |
158 from .node import ( |
159 from .node import ( |
159 hex, |
160 hex, |
160 short, |
161 short, |
178 from .utils import ( |
179 from .utils import ( |
179 stringutil, |
180 stringutil, |
180 urlutil, |
181 urlutil, |
181 ) |
182 ) |
182 from .interfaces import repository |
183 from .interfaces import repository |
|
184 |
|
185 if typing.TYPE_CHECKING: |
|
186 from typing import ( |
|
187 Dict, |
|
188 List, |
|
189 Optional, |
|
190 Tuple, |
|
191 Union, |
|
192 ) |
|
193 |
|
194 Capabilities = Dict[bytes, Union[List[bytes], Tuple[bytes, ...]]] |
183 |
195 |
184 urlerr = util.urlerr |
196 urlerr = util.urlerr |
185 urlreq = util.urlreq |
197 urlreq = util.urlreq |
186 |
198 |
187 _pack = struct.pack |
199 _pack = struct.pack |
600 outpart.addparam( |
612 outpart.addparam( |
601 b'in-reply-to', pycompat.bytestr(part.id), mandatory=False |
613 b'in-reply-to', pycompat.bytestr(part.id), mandatory=False |
602 ) |
614 ) |
603 |
615 |
604 |
616 |
605 def decodecaps(blob): |
617 def decodecaps(blob: bytes) -> "Capabilities": |
606 """decode a bundle2 caps bytes blob into a dictionary |
618 """decode a bundle2 caps bytes blob into a dictionary |
607 |
619 |
608 The blob is a list of capabilities (one per line) |
620 The blob is a list of capabilities (one per line) |
609 Capabilities may have values using a line of the form:: |
621 Capabilities may have values using a line of the form:: |
610 |
622 |
660 populate it. Then call `getchunks` to retrieve all the binary chunks of |
672 populate it. Then call `getchunks` to retrieve all the binary chunks of |
661 data that compose the bundle2 container.""" |
673 data that compose the bundle2 container.""" |
662 |
674 |
663 _magicstring = b'HG20' |
675 _magicstring = b'HG20' |
664 |
676 |
665 def __init__(self, ui, capabilities=()): |
677 def __init__(self, ui, capabilities: "Optional[Capabilities]" = None): |
|
678 if capabilities is None: |
|
679 capabilities = {} |
|
680 |
666 self.ui = ui |
681 self.ui = ui |
667 self._params = [] |
682 self._params = [] |
668 self._parts = [] |
683 self._parts = [] |
669 self.capabilities = dict(capabilities) |
684 self.capabilities: "Capabilities" = dict(capabilities) |
670 self._compengine = util.compengines.forbundletype(b'UN') |
685 self._compengine = util.compengines.forbundletype(b'UN') |
671 self._compopts = None |
686 self._compopts = None |
672 # If compression is being handled by a consumer of the raw |
687 # If compression is being handled by a consumer of the raw |
673 # data (e.g. the wire protocol), unsetting this flag tells |
688 # data (e.g. the wire protocol), unsetting this flag tells |
674 # consumers that the bundle is best left uncompressed. |
689 # consumers that the bundle is best left uncompressed. |
1610 return None |
1625 return None |
1611 |
1626 |
1612 |
1627 |
1613 # These are only the static capabilities. |
1628 # These are only the static capabilities. |
1614 # Check the 'getrepocaps' function for the rest. |
1629 # Check the 'getrepocaps' function for the rest. |
1615 capabilities = { |
1630 capabilities: "Capabilities" = { |
1616 b'HG20': (), |
1631 b'HG20': (), |
1617 b'bookmarks': (), |
1632 b'bookmarks': (), |
1618 b'error': (b'abort', b'unsupportedcontent', b'pushraced', b'pushkey'), |
1633 b'error': (b'abort', b'unsupportedcontent', b'pushraced', b'pushkey'), |
1619 b'listkeys': (), |
1634 b'listkeys': (), |
1620 b'pushkey': (), |
1635 b'pushkey': (), |
1624 b'phases': (b'heads',), |
1639 b'phases': (b'heads',), |
1625 b'stream': (b'v2',), |
1640 b'stream': (b'v2',), |
1626 } |
1641 } |
1627 |
1642 |
1628 |
1643 |
1629 def getrepocaps(repo, allowpushback=False, role=None): |
1644 # TODO: drop the default value for 'role' |
|
1645 def getrepocaps(repo, allowpushback: bool = False, role=None) -> "Capabilities": |
1630 """return the bundle2 capabilities for a given repo |
1646 """return the bundle2 capabilities for a given repo |
1631 |
1647 |
1632 Exists to allow extensions (like evolution) to mutate the capabilities. |
1648 Exists to allow extensions (like evolution) to mutate the capabilities. |
1633 |
1649 |
1634 The returned value is used for servers advertising their capabilities as |
1650 The returned value is used for servers advertising their capabilities as |
1673 # for legacy clients. |
1689 # for legacy clients. |
1674 |
1690 |
1675 return caps |
1691 return caps |
1676 |
1692 |
1677 |
1693 |
1678 def bundle2caps(remote): |
1694 def bundle2caps(remote) -> "Capabilities": |
1679 """return the bundle capabilities of a peer as dict""" |
1695 """return the bundle capabilities of a peer as dict""" |
1680 raw = remote.capable(b'bundle2') |
1696 raw = remote.capable(b'bundle2') |
1681 if not raw and raw != b'': |
1697 if not raw and raw != b'': |
1682 return {} |
1698 return {} |
1683 capsblob = urlreq.unquote(remote.capable(b'bundle2')) |
1699 capsblob = urlreq.unquote(remote.capable(b'bundle2')) |
1684 return decodecaps(capsblob) |
1700 return decodecaps(capsblob) |
1685 |
1701 |
1686 |
1702 |
1687 def obsmarkersversion(caps): |
1703 def obsmarkersversion(caps: "Capabilities"): |
1688 """extract the list of supported obsmarkers versions from a bundle2caps dict""" |
1704 """extract the list of supported obsmarkers versions from a bundle2caps dict""" |
1689 obscaps = caps.get(b'obsmarkers', ()) |
1705 obscaps = caps.get(b'obsmarkers', ()) |
1690 return [int(c[1:]) for c in obscaps if c.startswith(b'V')] |
1706 return [int(c[1:]) for c in obscaps if c.startswith(b'V')] |
1691 |
1707 |
1692 |
1708 |
1723 count = len(repo.revs(b'%ln and _internal()', outgoing.missing)) |
1739 count = len(repo.revs(b'%ln and _internal()', outgoing.missing)) |
1724 msg = "backup bundle would contains %d internal changesets" |
1740 msg = "backup bundle would contains %d internal changesets" |
1725 msg %= count |
1741 msg %= count |
1726 raise error.ProgrammingError(msg) |
1742 raise error.ProgrammingError(msg) |
1727 |
1743 |
1728 caps = {} |
1744 caps: "Capabilities" = {} |
1729 if opts.get(b'obsolescence', False): |
1745 if opts.get(b'obsolescence', False): |
1730 caps[b'obsmarkers'] = (b'V1',) |
1746 caps[b'obsmarkers'] = (b'V1',) |
1731 stream_version = opts.get(b'stream', b"") |
1747 stream_version = opts.get(b'stream', b"") |
1732 if stream_version == b"v2": |
1748 if stream_version == b"v2": |
1733 caps[b'stream'] = [b'v2'] |
1749 caps[b'stream'] = [b'v2'] |