schemes.py
149 lines
| 4.3 KiB
| text/x-python
|
PythonLexer
/ hgext / schemes.py
Alexander Solovyov
|
r9964 | # Copyright 2009, Alexander Solovyov <piranha@piranha.org.ua> | ||
# | ||||
# This software may be used and distributed according to the terms of the | ||||
Matt Mackall
|
r10263 | # GNU General Public License version 2 or any later version. | ||
Alexander Solovyov
|
r9964 | |||
"""extend schemes with shortcuts to repository swarms | ||||
This extension allows you to specify shortcuts for parent URLs with a | ||||
lot of repositories to act like a scheme, for example:: | ||||
[schemes] | ||||
py = http://code.python.org/hg/ | ||||
After that you can use it like:: | ||||
hg clone py://trunk/ | ||||
Additionally there is support for some more complex schemas, for | ||||
example used by Google Code:: | ||||
[schemes] | ||||
gcode = http://{1}.googlecode.com/hg/ | ||||
The syntax is taken from Mercurial templates, and you have unlimited | ||||
number of variables, starting with ``{1}`` and continuing with | ||||
``{2}``, ``{3}`` and so on. This variables will receive parts of URL | ||||
supplied, split by ``/``. Anything not specified as ``{part}`` will be | ||||
just appended to an URL. | ||||
For convenience, the extension adds these schemes by default:: | ||||
[schemes] | ||||
py = http://hg.python.org/ | ||||
bb = https://bitbucket.org/ | ||||
bb+ssh = ssh://hg@bitbucket.org/ | ||||
gcode = https://{1}.googlecode.com/hg/ | ||||
Benjamin Pollack
|
r10777 | kiln = https://{1}.kilnhg.com/Repo/ | ||
Alexander Solovyov
|
r9964 | |||
Martin Geisler
|
r9965 | You can override a predefined scheme by defining a new scheme with the | ||
same name. | ||||
Alexander Solovyov
|
r9964 | """ | ||
timeless
|
r28379 | from __future__ import absolute_import | ||
Alexander Solovyov
|
r9964 | |||
timeless
|
r28379 | import os | ||
import re | ||||
Yuya Nishihara
|
r29205 | |||
from mercurial.i18n import _ | ||||
timeless
|
r28379 | from mercurial import ( | ||
error, | ||||
extensions, | ||||
hg, | ||||
Pulkit Goyal
|
r30640 | pycompat, | ||
Yuya Nishihara
|
r32337 | registrar, | ||
timeless
|
r28379 | templater, | ||
util, | ||||
) | ||||
Alexander Solovyov
|
r9964 | |||
Jason R. Coombs
|
r27982 | cmdtable = {} | ||
Yuya Nishihara
|
r32337 | command = registrar.command(cmdtable) | ||
Augie Fackler
|
r29841 | # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for | ||
Augie Fackler
|
r25186 | # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should | ||
# be specifying the version(s) of Mercurial they are tested with, or | ||||
# leave the attribute unspecified. | ||||
Augie Fackler
|
r43347 | testedwith = b'ships-with-hg-core' | ||
Augie Fackler
|
r16743 | |||
Matt Harbison
|
r44474 | _partre = re.compile(br'{(\d+)\}') | ||
Alexander Solovyov
|
r9964 | |||
Augie Fackler
|
r43346 | |||
Alexander Solovyov
|
r9964 | class ShortRepository(object): | ||
def __init__(self, url, scheme, templater): | ||||
self.scheme = scheme | ||||
self.templater = templater | ||||
self.url = url | ||||
try: | ||||
Augie Fackler
|
r31181 | self.parts = max(map(int, _partre.findall(self.url))) | ||
Alexander Solovyov
|
r9964 | except ValueError: | ||
self.parts = 0 | ||||
def __repr__(self): | ||||
Augie Fackler
|
r43347 | return b'<ShortRepository: %s>' % self.scheme | ||
Alexander Solovyov
|
r9964 | |||
Gregory Szorc
|
r39585 | def instance(self, ui, url, create, intents=None, createopts=None): | ||
Jason R. Coombs
|
r27981 | url = self.resolve(url) | ||
Augie Fackler
|
r43346 | return hg._peerlookup(url).instance( | ||
ui, url, create, intents=intents, createopts=createopts | ||||
) | ||||
Jason R. Coombs
|
r27981 | |||
def resolve(self, url): | ||||
Mads Kiilerich
|
r17425 | # Should this use the util.url class, or is manual parsing better? | ||
Mads Kiilerich
|
r18910 | try: | ||
Augie Fackler
|
r43347 | url = url.split(b'://', 1)[1] | ||
Mads Kiilerich
|
r18910 | except IndexError: | ||
Augie Fackler
|
r43347 | raise error.Abort(_(b"no '://' in scheme url '%s'") % url) | ||
parts = url.split(b'/', self.parts) | ||||
Alexander Solovyov
|
r9964 | if len(parts) > self.parts: | ||
tail = parts[-1] | ||||
parts = parts[:-1] | ||||
else: | ||||
Augie Fackler
|
r43347 | tail = b'' | ||
Augie Fackler
|
r44937 | context = {b'%d' % (i + 1): v for i, v in enumerate(parts)} | ||
Augie Fackler
|
r43347 | return b''.join(self.templater.process(self.url, context)) + tail | ||
Alexander Solovyov
|
r9964 | |||
Augie Fackler
|
r43346 | |||
Matt Mackall
|
r13827 | def hasdriveletter(orig, path): | ||
Patrick Mezard
|
r15609 | if path: | ||
for scheme in schemes: | ||||
Augie Fackler
|
r43347 | if path.startswith(scheme + b':'): | ||
Patrick Mezard
|
r15609 | return False | ||
Brodie Rao
|
r13822 | return orig(path) | ||
Augie Fackler
|
r43346 | |||
Alexander Solovyov
|
r9964 | schemes = { | ||
Augie Fackler
|
r43347 | b'py': b'http://hg.python.org/', | ||
b'bb': b'https://bitbucket.org/', | ||||
b'bb+ssh': b'ssh://hg@bitbucket.org/', | ||||
b'gcode': b'https://{1}.googlecode.com/hg/', | ||||
b'kiln': b'https://{1}.kilnhg.com/Repo/', | ||||
Augie Fackler
|
r43346 | } | ||
Alexander Solovyov
|
r9964 | |||
def extsetup(ui): | ||||
Augie Fackler
|
r43347 | schemes.update(dict(ui.configitems(b'schemes'))) | ||
Yuya Nishihara
|
r38373 | t = templater.engine(templater.parse) | ||
Alexander Solovyov
|
r9964 | for scheme, url in schemes.items(): | ||
Augie Fackler
|
r43346 | if ( | ||
pycompat.iswindows | ||||
and len(scheme) == 1 | ||||
and scheme.isalpha() | ||||
Augie Fackler
|
r43347 | and os.path.exists(b'%s:\\' % scheme) | ||
Augie Fackler
|
r43346 | ): | ||
raise error.Abort( | ||||
Augie Fackler
|
r43347 | _( | ||
b'custom scheme %s:// conflicts with drive ' | ||||
b'letter %s:\\\n' | ||||
) | ||||
Augie Fackler
|
r43346 | % (scheme, scheme.upper()) | ||
) | ||||
Matt Mackall
|
r14606 | hg.schemes[scheme] = ShortRepository(url, scheme, t) | ||
Brodie Rao
|
r13822 | |||
Augie Fackler
|
r43347 | extensions.wrapfunction(util, b'hasdriveletter', hasdriveletter) | ||
Jason R. Coombs
|
r27982 | |||
Augie Fackler
|
r43346 | |||
Augie Fackler
|
r43347 | @command(b'debugexpandscheme', norepo=True) | ||
Jason R. Coombs
|
r27982 | def expandscheme(ui, url, **opts): | ||
Augie Fackler
|
r46554 | """given a repo path, provide the scheme-expanded path""" | ||
Jason R. Coombs
|
r27982 | repo = hg._peerlookup(url) | ||
if isinstance(repo, ShortRepository): | ||||
url = repo.resolve(url) | ||||
Augie Fackler
|
r43347 | ui.write(url + b'\n') | ||