Mercurial URL Parser - libvcs.url.hg#

For hg, aka hg(1).

This module is an all-in-one parser and validator for Mercurial URLs.

Note

Do you use Mercurial at your job or project? This module welcomes a champion / maintainer to assure support is top-tier. Stop by the project tracker to make yourself known. We won’t stabilize any APIs until we’re satisfied support is β€œby the book” and is bullet proofed.

libvcs.url.hg.DEFAULT_RULES: list[libvcs.url.base.Rule] = [Rule(label=core-hg, description=Vanilla hg pattern, pattern=re.compile('\n        ^\n    (?P<scheme>\n      (\n        http|https|ssh\n      )\n    )\n\n        ://\n        \n    ((?P<user>\\w+)@)?\n    (?P<hostname>([^/:]+))\n    (:(?P<port>\\d{1,5}))?\n    (?P<separat, re.VERBOSE), defaults={}), Rule(label=core-hg-scp, description=Vanilla scp(1) / ssh(1) type URL, pattern=re.compile("\n        ^(?P<scheme>ssh)?\n        \n    # Optional user, e.g. 'git@'\n    ((?P<user>\\w+)@)?\n    # Server, e.g. 'github.com'.\n    (?P<hostname>([^/:]+))\n    (?P<separator>:)\n    # The server-s, re.VERBOSE), defaults={'username': 'hg'})]#

Core regular expressions. These are patterns understood by hg(1)

libvcs.url.hg.PIP_DEFAULT_RULES: list[libvcs.url.base.Rule] = [Rule(label=pip-url, description=pip-style hg URL, pattern=re.compile('\n        ^\n    (?P<scheme>\n      (\n        hg\\+ssh|\n        hg\\+https|\n        hg\\+http|\n        hg\\+file\n      )\n    )\n\n        ://\n        \n    ((?P<user>\\w+)@)?\n    (?P<hostname, re.VERBOSE), defaults={}, is_explicit=True), Rule(label=pip-file-url, description=pip-style hg+file:// URL, pattern=re.compile('\n        (?P<scheme>hg\\+file)://\n        (?P<path>.*)\n        ', re.VERBOSE), defaults={}, is_explicit=True)]#

pip-style hg URLs.

Examples of PIP-style hg URLs (via pip.pypa.io):

MyProject @ hg+http://hg.myproject.org/MyProject
MyProject @ hg+https://hg.myproject.org/MyProject
MyProject @ hg+ssh://hg.myproject.org/MyProject
MyProject @ hg+file:///home/user/projects/MyProject

Refs (via pip.pypa.io):

MyProject @ hg+http://hg.example.com/MyProject@da39a3ee5e6b
MyProject @ hg+http://hg.example.com/MyProject@2019
MyProject @ hg+http://hg.example.com/MyProject@v1.0
MyProject @ hg+http://hg.example.com/MyProject@special_feature

Notes

class libvcs.url.hg.HgBaseURL(url, scheme=None, user=None, hostname='', port=None, separator='/', path='', suffix=None, ref=None, rule=None, rule_map=RuleMap(_rule_map={'core-hg': Rule(label=core-hg, description=Vanilla hg pattern, pattern=re.compile('\\n        ^\\n    (?P<scheme>\\n      (\\n        http|https|ssh\\n      )\\n    )\\n\\n        ://\\n        \\n    ((?P<user>\\\\w+)@)?\\n    (?P<hostname>([^/:]+))\\n    (:(?P<port>\\\\d{1, 5}))?\\n    (?P<separat, re.VERBOSE), defaults={}), 'core-hg-scp': Rule(label=core-hg-scp, description=Vanilla scp(1) / ssh(1) type URL, pattern=re.compile("\\n        ^(?P<scheme>ssh)?\\n        \\n    # Optional user, e.g. 'git@'\\n    ((?P<user>\\\\w+)@)?\\n    # Server, e.g. 'github.com'.\\n    (?P<hostname>([^/:]+))\\n    (?P<separator>:)\\n    # The server-s, re.VERBOSE), defaults={'username': 'hg'})}))[source]#

Bases: URLProtocol, SkipDefaultFieldsReprMixin

Mercurial repository location. Parses URLs on initialization.

Parameters:
rule#

name of the Rule

Type:

str

Examples

>>> HgBaseURL(url='https://hg.mozilla.org/mozilla-central/')
HgBaseURL(url=https://hg.mozilla.org/mozilla-central/,
        scheme=https,
        hostname=hg.mozilla.org,
        path=mozilla-central/,
        rule=core-hg)
>>> myrepo = HgURL(url='https://hg.mozilla.org/mozilla-central/')
>>> myrepo.hostname
'hg.mozilla.org'
>>> myrepo.path
'mozilla-central/'
>>> HgBaseURL.is_valid(url='ssh://[email protected]/path/to/repo')
True
>>> HgBaseURL(url='ssh://[email protected]/path/to/repo')
HgBaseURL(url=ssh://[email protected]/path/to/repo,
        scheme=ssh,
        user=username,
        hostname=machinename,
        path=path/to/repo,
        rule=core-hg)
url: str#
scheme: Optional[str] = None#
user: Optional[str] = None#
hostname: str = ''#
port: Optional[int] = None#
separator: str = '/'#
path: str = ''#
suffix: Optional[str] = None#
ref: Optional[str] = None#
rule: Optional[str] = None#
rule_map: RuleMap = RuleMap(_rule_map={'core-hg': Rule(label=core-hg, description=Vanilla hg pattern, pattern=re.compile('\n        ^\n    (?P<scheme>\n      (\n        http|https|ssh\n      )\n    )\n\n        ://\n        \n    ((?P<user>\\w+)@)?\n    (?P<hostname>([^/:]+))\n    (:(?P<port>\\d{1,5}))?\n    (?P<separat, re.VERBOSE), defaults={}), 'core-hg-scp': Rule(label=core-hg-scp, description=Vanilla scp(1) / ssh(1) type URL, pattern=re.compile("\n        ^(?P<scheme>ssh)?\n        \n    # Optional user, e.g. 'git@'\n    ((?P<user>\\w+)@)?\n    # Server, e.g. 'github.com'.\n    (?P<hostname>([^/:]+))\n    (?P<separator>:)\n    # The server-s, re.VERBOSE), defaults={'username': 'hg'})})#
classmethod is_valid(url, is_explicit=None)[source]#

Whether URL is compatible with VCS or not.

Examples

>>> HgBaseURL.is_valid(
...     url='https://hg.mozilla.org/mozilla-central'
... )
True
>>> HgBaseURL.is_valid(url='ssh://[email protected]/cpython')
True
>>> HgBaseURL.is_valid(url='notaurl')
False
Return type:

bool

Parameters:
to_url()[source]#

Return a hg(1)-compatible URL. Can be used with hg clone.

Examples

>>> hg_url = HgBaseURL(url='https://hg.mozilla.org/mozilla-central')
>>> hg_url
HgBaseURL(url=https://hg.mozilla.org/mozilla-central,
        scheme=https,
        hostname=hg.mozilla.org,
        path=mozilla-central,
        rule=core-hg)

Switch repo libvcs -> vcspull:

>>> hg_url.path = 'mobile-browser'
>>> hg_url.to_url()
'https://hg.mozilla.org/mobile-browser'

Switch them to localhost:

>>> hg_url.hostname = 'localhost'
>>> hg_url.scheme = 'http'
>>> hg_url.to_url()
'http://localhost/mobile-browser'

Another example, hugin:

>>> hugin = HgBaseURL(
...     url="http://hugin.hg.sourceforge.net:8000/hgroot/hugin/hugin")
>>> hugin
HgBaseURL(url=http://hugin.hg.sourceforge.net:8000/hgroot/hugin/hugin,
        scheme=http,
        hostname=hugin.hg.sourceforge.net,
        port=8000,
        path=hgroot/hugin/hugin,
        rule=core-hg)
>>> hugin.to_url()
'http://hugin.hg.sourceforge.net:8000/hgroot/hugin/hugin'

SSH URL with a username, graphicsmagic:

>>> graphicsmagick = HgBaseURL(
...     url="ssh://[email protected]//hg/GraphicsMagick"
... )
>>> graphicsmagick
HgBaseURL(url=ssh://[email protected]//hg/GraphicsMagick,
        scheme=ssh,
        user=yourid,
        hostname=hg.GraphicsMagick.org,
        path=/hg/GraphicsMagick,
        rule=core-hg)
>>> graphicsmagick.to_url()
'ssh://[email protected]//hg/GraphicsMagick'

Switch the username:

>>> graphicsmagick.user = 'lucas'
>>> graphicsmagick.to_url()
'ssh://[email protected]//hg/GraphicsMagick'
Return type:

str

_abc_impl = <_abc._abc_data object>#
_is_protocol = False#
class libvcs.url.hg.HgPipURL(url, scheme=None, user=None, hostname='', port=None, separator='/', path='', suffix=None, ref=None, rule=None, rule_map=RuleMap(_rule_map={'pip-url': Rule(label=pip-url, description=pip-style hg URL, pattern=re.compile('\\n        ^\\n    (?P<scheme>\\n      (\\n        hg\\\\+ssh|\\n        hg\\\\+https|\\n        hg\\\\+http|\\n        hg\\\\+file\\n      )\\n    )\\n\\n        ://\\n        \\n    ((?P<user>\\\\w+)@)?\\n    (?P<hostname, re.VERBOSE), defaults={}, is_explicit=True), 'pip-file-url': Rule(label=pip-file-url, description=pip-style hg+file:// URL, pattern=re.compile('\\n        (?P<scheme>hg\\\\+file)://\\n        (?P<path>.*)\\n        ', re.VERBOSE), defaults={}, is_explicit=True)}), rev=None)[source]#

Bases: HgBaseURL, URLProtocol, SkipDefaultFieldsReprMixin

Supports pip hg URLs.

Parameters:
rev: Optional[str] = None#
rule_map: RuleMap = RuleMap(_rule_map={'pip-url': Rule(label=pip-url, description=pip-style hg URL, pattern=re.compile('\n        ^\n    (?P<scheme>\n      (\n        hg\\+ssh|\n        hg\\+https|\n        hg\\+http|\n        hg\\+file\n      )\n    )\n\n        ://\n        \n    ((?P<user>\\w+)@)?\n    (?P<hostname, re.VERBOSE), defaults={}, is_explicit=True), 'pip-file-url': Rule(label=pip-file-url, description=pip-style hg+file:// URL, pattern=re.compile('\n        (?P<scheme>hg\\+file)://\n        (?P<path>.*)\n        ', re.VERBOSE), defaults={}, is_explicit=True)})#
classmethod is_valid(url, is_explicit=None)[source]#

Whether URL is compatible with VCS or not.

Examples

>>> HgPipURL.is_valid(
...     url='hg+https://hg.mozilla.org/mozilla-central'
... )
True
>>> HgPipURL.is_valid(url='hg+ssh://[email protected]:cpython')
True
>>> HgPipURL.is_valid(url='notaurl')
False
Return type:

bool

Parameters:
to_url()[source]#

Return a hg(1)-compatible URL. Can be used with hg clone.

Examples

>>> hg_url = HgPipURL(url='hg+https://hg.mozilla.org/mozilla-central')
>>> hg_url
HgPipURL(url=hg+https://hg.mozilla.org/mozilla-central,
        scheme=hg+https,
        hostname=hg.mozilla.org,
        path=mozilla-central,
        rule=pip-url)

Switch repo mozilla-central -> mobile-browser:

>>> hg_url.path = 'mobile-browser'
>>> hg_url.to_url()
'hg+https://hg.mozilla.org/mobile-browser'

Switch them to localhost:

>>> hg_url.hostname = 'localhost'
>>> hg_url.scheme = 'http'
>>> hg_url.to_url()
'http://localhost/mobile-browser'
Return type:

str

_abc_impl = <_abc._abc_data object>#
_is_protocol = False#
class libvcs.url.hg.HgURL(url, scheme=None, user=None, hostname='', port=None, separator='/', path='', suffix=None, ref=None, rule=None, rule_map=RuleMap(_rule_map={'core-hg': Rule(label=core-hg, description=Vanilla hg pattern, pattern=re.compile('\\n        ^\\n    (?P<scheme>\\n      (\\n        http|https|ssh\\n      )\\n    )\\n\\n        ://\\n        \\n    ((?P<user>\\\\w+)@)?\\n    (?P<hostname>([^/:]+))\\n    (:(?P<port>\\\\d{1, 5}))?\\n    (?P<separat, re.VERBOSE), defaults={}), 'core-hg-scp': Rule(label=core-hg-scp, description=Vanilla scp(1) / ssh(1) type URL, pattern=re.compile("\\n        ^(?P<scheme>ssh)?\\n        \\n    # Optional user, e.g. 'git@'\\n    ((?P<user>\\\\w+)@)?\\n    # Server, e.g. 'github.com'.\\n    (?P<hostname>([^/:]+))\\n    (?P<separator>:)\\n    # The server-s, re.VERBOSE), defaults={'username': 'hg'}), 'pip-url': Rule(label=pip-url, description=pip-style hg URL, pattern=re.compile('\\n        ^\\n    (?P<scheme>\\n      (\\n        hg\\\\+ssh|\\n        hg\\\\+https|\\n        hg\\\\+http|\\n        hg\\\\+file\\n      )\\n    )\\n\\n        ://\\n        \\n    ((?P<user>\\\\w+)@)?\\n    (?P<hostname, re.VERBOSE), defaults={}, is_explicit=True), 'pip-file-url': Rule(label=pip-file-url, description=pip-style hg+file:// URL, pattern=re.compile('\\n        (?P<scheme>hg\\\\+file)://\\n        (?P<path>.*)\\n        ', re.VERBOSE), defaults={}, is_explicit=True)}), rev=None)[source]#

Bases: HgPipURL, HgBaseURL, URLProtocol, SkipDefaultFieldsReprMixin

Batteries included URL Parser. Supports hg(1) and pip URLs.

Ancestors (MRO) This URL parser inherits methods and attributes from the following parsers:

Parameters:
rule_map: RuleMap = RuleMap(_rule_map={'core-hg': Rule(label=core-hg, description=Vanilla hg pattern, pattern=re.compile('\n        ^\n    (?P<scheme>\n      (\n        http|https|ssh\n      )\n    )\n\n        ://\n        \n    ((?P<user>\\w+)@)?\n    (?P<hostname>([^/:]+))\n    (:(?P<port>\\d{1,5}))?\n    (?P<separat, re.VERBOSE), defaults={}), 'core-hg-scp': Rule(label=core-hg-scp, description=Vanilla scp(1) / ssh(1) type URL, pattern=re.compile("\n        ^(?P<scheme>ssh)?\n        \n    # Optional user, e.g. 'git@'\n    ((?P<user>\\w+)@)?\n    # Server, e.g. 'github.com'.\n    (?P<hostname>([^/:]+))\n    (?P<separator>:)\n    # The server-s, re.VERBOSE), defaults={'username': 'hg'}), 'pip-url': Rule(label=pip-url, description=pip-style hg URL, pattern=re.compile('\n        ^\n    (?P<scheme>\n      (\n        hg\\+ssh|\n        hg\\+https|\n        hg\\+http|\n        hg\\+file\n      )\n    )\n\n        ://\n        \n    ((?P<user>\\w+)@)?\n    (?P<hostname, re.VERBOSE), defaults={}, is_explicit=True), 'pip-file-url': Rule(label=pip-file-url, description=pip-style hg+file:// URL, pattern=re.compile('\n        (?P<scheme>hg\\+file)://\n        (?P<path>.*)\n        ', re.VERBOSE), defaults={}, is_explicit=True)})#
_abc_impl = <_abc._abc_data object>#
_is_protocol = False#
classmethod is_valid(url, is_explicit=None)[source]#

Whether URL is compatible included Hg URL rule_map or not.

Examples

Will match normal hg(1) URLs, use HgURL.is_valid() for that.

>>> HgURL.is_valid(url='https://hg.mozilla.org/mozilla-central/mozilla-central')
True
>>> HgURL.is_valid(url='[email protected]:MyProject/project')
True

Pip-style URLs:

>>> HgURL.is_valid(url='hg+https://hg.mozilla.org/mozilla-central/project')
True
>>> HgURL.is_valid(url='hg+ssh://[email protected]:MyProject/project')
True
>>> HgURL.is_valid(url='notaurl')
False

Explicit VCS detection

Pip-style URLs are prefixed with the VCS name in front, so its rule_map can unambigously narrow the type of VCS:

>>> HgURL.is_valid(
...     url='hg+ssh://[email protected]:mozilla-central/image', is_explicit=True
... )
True

Below, while it’s hg.mozilla.org, that doesn’t necessarily mean that the URL itself is conclusively a hg URL (e.g. the pattern is too broad):

>>> HgURL.is_valid(
...     url='[email protected]:mozilla-central/image', is_explicit=True
... )
False

You could create a Mozilla rule that consider hg.mozilla.org hostnames to be exclusively hg:

>>> MozillaRule = Rule(
...     # Since hg.mozilla.org exclusively serves hg repos, make explicit
...     label='mozilla-rule',
...     description='Matches hg.mozilla.org https URLs, exact VCS match',
...     pattern=re.compile(
...         rf'''
...         ^(?P<scheme>ssh)?
...         ((?P<user>\w+)@)?
...         (?P<hostname>(hg.mozilla.org)+):
...         (?P<path>(\w[^:]+))
...         {RE_SUFFIX}?
...         ''',
...         re.VERBOSE,
...     ),
...     is_explicit=True,
...     defaults={
...         'hostname': 'hg.mozilla.org'
...     }
... )
>>> HgURL.rule_map.register(MozillaRule)
>>> HgURL.is_valid(
...     url='[email protected]:mozilla-central/image', is_explicit=True
... )
True
>>> HgURL(url='[email protected]:mozilla-central/image').rule
'mozilla-rule'

This is just us cleaning up:

>>> HgURL.rule_map.unregister('mozilla-rule')
>>> HgURL(url='[email protected]:mozilla-central/mozilla-rule').rule
'core-hg-scp'
Return type:

bool

Parameters:
to_url()[source]#

Return a hg(1)-compatible URL. Can be used with hg clone.

Examples

SSH style URL:

>>> hg_url = HgURL(url='[email protected]:mozilla-central/browser')
>>> hg_url.path = 'mozilla-central/gfx'
>>> hg_url.to_url()
'ssh://[email protected]:mozilla-central/gfx'

HTTPs URL:

>>> hg_url = HgURL(url='https://hg.mozilla.org/mozilla-central/memory')
>>> hg_url.path = 'mozilla-central/image'
>>> hg_url.to_url()
'https://hg.mozilla.org/mozilla-central/image'

Switch them to hglab:

>>> hg_url.hostname = 'localhost'
>>> hg_url.scheme = 'http'
>>> hg_url.to_url()
'http://localhost/mozilla-central/image'

Pip style URL, thanks to this class implementing HgPipURL:

>>> hg_url = HgURL(url='hg+ssh://[email protected]/mozilla-central/image')
>>> hg_url.hostname = 'localhost'
>>> hg_url.to_url()
'hg+ssh://[email protected]/mozilla-central/image'
>>> hg_url.user = None
>>> hg_url.to_url()
'hg+ssh://localhost/mozilla-central/image'
Return type:

str