schemes: prevent one letter schemes from being interpreted as drive letters

To allow one letter schemes, this makes the extension override
url.has_drive_letter() to return False for any schemes defined.

On Windows, the extension will raise util.Abort for any schemes that
conflict with existing drive letters.
This commit is contained in:
Brodie Rao 2011-03-30 20:01:47 -07:00
parent 744f9e0914
commit 475e3772da

View File

@ -40,8 +40,9 @@ You can override a predefined scheme by defining a new scheme with the
same name.
"""
import re
from mercurial import hg, templater
import os, re
from mercurial import extensions, hg, templater, url as urlmod, util
from mercurial.i18n import _
class ShortRepository(object):
@ -58,6 +59,7 @@ class ShortRepository(object):
return '<ShortRepository: %s>' % self.scheme
def instance(self, ui, url, create):
# Should this use urlmod.url(), or is manual parsing better?
url = url.split('://', 1)[1]
parts = url.split('/', self.parts)
if len(parts) > self.parts:
@ -69,6 +71,12 @@ class ShortRepository(object):
url = ''.join(self.templater.process(self.url, context)) + tail
return hg._lookup(url).instance(ui, url, create)
def has_drive_letter(orig, path):
for scheme in schemes:
if path.startswith(scheme + ':'):
return False
return orig(path)
schemes = {
'py': 'http://hg.python.org/',
'bb': 'https://bitbucket.org/',
@ -81,4 +89,10 @@ def extsetup(ui):
schemes.update(dict(ui.configitems('schemes')))
t = templater.engine(lambda x: x)
for scheme, url in schemes.items():
if (os.name == 'nt' and len(scheme) == 1 and scheme.isalpha()
and os.path.exists('%s:\\' % scheme)):
raise util.Abort(_('custom scheme %s:// conflicts with drive '
'letter %s:\\\n') % (scheme, scheme.upper()))
hg.schemes[scheme] = ShortRepository(url, scheme, t)
extensions.wrapfunction(urlmod, 'has_drive_letter', has_drive_letter)