##// END OF EJS Templates
url: move URL parsing functions into util to improve startup time...
Brodie Rao -
r14076:924c8215 default
parent child Browse files
Show More
@@ -9,7 +9,7 b''
9
9
10 from mercurial.i18n import _
10 from mercurial.i18n import _
11 from mercurial.node import nullid, short
11 from mercurial.node import nullid, short
12 from mercurial import commands, cmdutil, hg, util, url, error
12 from mercurial import commands, cmdutil, hg, util, error
13 from mercurial.lock import release
13 from mercurial.lock import release
14
14
15 def fetch(ui, repo, source='default', **opts):
15 def fetch(ui, repo, source='default', **opts):
@@ -66,7 +66,7 b" def fetch(ui, repo, source='default', **"
66 other = hg.repository(hg.remoteui(repo, opts),
66 other = hg.repository(hg.remoteui(repo, opts),
67 ui.expandpath(source))
67 ui.expandpath(source))
68 ui.status(_('pulling from %s\n') %
68 ui.status(_('pulling from %s\n') %
69 url.hidepassword(ui.expandpath(source)))
69 util.hidepassword(ui.expandpath(source)))
70 revs = None
70 revs = None
71 if opts['rev']:
71 if opts['rev']:
72 try:
72 try:
@@ -125,7 +125,7 b" def fetch(ui, repo, source='default', **"
125 # we don't translate commit messages
125 # we don't translate commit messages
126 message = (cmdutil.logmessage(opts) or
126 message = (cmdutil.logmessage(opts) or
127 ('Automated merge with %s' %
127 ('Automated merge with %s' %
128 url.removeauth(other.url())))
128 util.removeauth(other.url())))
129 editor = cmdutil.commiteditor
129 editor = cmdutil.commiteditor
130 if opts.get('force_editor') or opts.get('edit'):
130 if opts.get('force_editor') or opts.get('edit'):
131 editor = cmdutil.commitforceeditor
131 editor = cmdutil.commitforceeditor
@@ -48,7 +48,7 b' hgrc(5) for details.'
48 import os, errno, socket, tempfile, cStringIO, time
48 import os, errno, socket, tempfile, cStringIO, time
49 import email.MIMEMultipart, email.MIMEBase
49 import email.MIMEMultipart, email.MIMEBase
50 import email.Utils, email.Encoders, email.Generator
50 import email.Utils, email.Encoders, email.Generator
51 from mercurial import cmdutil, commands, hg, mail, patch, util, discovery, url
51 from mercurial import cmdutil, commands, hg, mail, patch, util, discovery
52 from mercurial.i18n import _
52 from mercurial.i18n import _
53 from mercurial.node import bin
53 from mercurial.node import bin
54
54
@@ -239,7 +239,7 b' def patchbomb(ui, repo, *revs, **opts):'
239 dest, branches = hg.parseurl(dest)
239 dest, branches = hg.parseurl(dest)
240 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
240 revs, checkout = hg.addbranchrevs(repo, repo, branches, revs)
241 other = hg.repository(hg.remoteui(repo, opts), dest)
241 other = hg.repository(hg.remoteui(repo, opts), dest)
242 ui.status(_('comparing with %s\n') % url.hidepassword(dest))
242 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
243 common, _anyinc, _heads = discovery.findcommonincoming(repo, other)
243 common, _anyinc, _heads = discovery.findcommonincoming(repo, other)
244 nodes = revs and map(repo.lookup, revs) or revs
244 nodes = revs and map(repo.lookup, revs) or revs
245 o = repo.changelog.findmissing(common, heads=nodes)
245 o = repo.changelog.findmissing(common, heads=nodes)
@@ -41,7 +41,7 b' same name.'
41 """
41 """
42
42
43 import os, re
43 import os, re
44 from mercurial import extensions, hg, templater, url as urlmod, util
44 from mercurial import extensions, hg, templater, util
45 from mercurial.i18n import _
45 from mercurial.i18n import _
46
46
47
47
@@ -95,4 +95,4 b' def extsetup(ui):'
95 'letter %s:\\\n') % (scheme, scheme.upper()))
95 'letter %s:\\\n') % (scheme, scheme.upper()))
96 hg.schemes[scheme] = ShortRepository(url, scheme, t)
96 hg.schemes[scheme] = ShortRepository(url, scheme, t)
97
97
98 extensions.wrapfunction(urlmod, 'hasdriveletter', hasdriveletter)
98 extensions.wrapfunction(util, 'hasdriveletter', hasdriveletter)
@@ -15,7 +15,7 b' from node import nullid'
15 from i18n import _
15 from i18n import _
16 import os, struct, tempfile, shutil
16 import os, struct, tempfile, shutil
17 import changegroup, util, mdiff, discovery
17 import changegroup, util, mdiff, discovery
18 import localrepo, changelog, manifest, filelog, revlog, error, url
18 import localrepo, changelog, manifest, filelog, revlog, error
19
19
20 class bundlerevlog(revlog.revlog):
20 class bundlerevlog(revlog.revlog):
21 def __init__(self, opener, indexfile, bundle,
21 def __init__(self, opener, indexfile, bundle,
@@ -274,7 +274,7 b' def instance(ui, path, create):'
274 cwd = os.path.join(cwd,'')
274 cwd = os.path.join(cwd,'')
275 if parentpath.startswith(cwd):
275 if parentpath.startswith(cwd):
276 parentpath = parentpath[len(cwd):]
276 parentpath = parentpath[len(cwd):]
277 u = url.url(path)
277 u = util.url(path)
278 path = u.localpath()
278 path = u.localpath()
279 if u.scheme == 'bundle':
279 if u.scheme == 'bundle':
280 s = path.split("+", 1)
280 s = path.split("+", 1)
@@ -2607,7 +2607,7 b' def incoming(ui, repo, source="default",'
2607 if 'bookmarks' not in other.listkeys('namespaces'):
2607 if 'bookmarks' not in other.listkeys('namespaces'):
2608 ui.warn(_("remote doesn't support bookmarks\n"))
2608 ui.warn(_("remote doesn't support bookmarks\n"))
2609 return 0
2609 return 0
2610 ui.status(_('comparing with %s\n') % url.hidepassword(source))
2610 ui.status(_('comparing with %s\n') % util.hidepassword(source))
2611 return bookmarks.diff(ui, repo, other)
2611 return bookmarks.diff(ui, repo, other)
2612
2612
2613 ret = hg.incoming(ui, repo, source, opts)
2613 ret = hg.incoming(ui, repo, source, opts)
@@ -2894,7 +2894,7 b' def outgoing(ui, repo, dest=None, **opts'
2894 if 'bookmarks' not in other.listkeys('namespaces'):
2894 if 'bookmarks' not in other.listkeys('namespaces'):
2895 ui.warn(_("remote doesn't support bookmarks\n"))
2895 ui.warn(_("remote doesn't support bookmarks\n"))
2896 return 0
2896 return 0
2897 ui.status(_('comparing with %s\n') % url.hidepassword(dest))
2897 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
2898 return bookmarks.diff(ui, other, repo)
2898 return bookmarks.diff(ui, other, repo)
2899
2899
2900 ret = hg.outgoing(ui, repo, dest, opts)
2900 ret = hg.outgoing(ui, repo, dest, opts)
@@ -2968,13 +2968,13 b' def paths(ui, repo, search=None):'
2968 if search:
2968 if search:
2969 for name, path in ui.configitems("paths"):
2969 for name, path in ui.configitems("paths"):
2970 if name == search:
2970 if name == search:
2971 ui.write("%s\n" % url.hidepassword(path))
2971 ui.write("%s\n" % util.hidepassword(path))
2972 return
2972 return
2973 ui.warn(_("not found!\n"))
2973 ui.warn(_("not found!\n"))
2974 return 1
2974 return 1
2975 else:
2975 else:
2976 for name, path in ui.configitems("paths"):
2976 for name, path in ui.configitems("paths"):
2977 ui.write("%s = %s\n" % (name, url.hidepassword(path)))
2977 ui.write("%s = %s\n" % (name, util.hidepassword(path)))
2978
2978
2979 def postincoming(ui, repo, modheads, optupdate, checkout):
2979 def postincoming(ui, repo, modheads, optupdate, checkout):
2980 if modheads == 0:
2980 if modheads == 0:
@@ -3017,7 +3017,7 b' def pull(ui, repo, source="default", **o'
3017 """
3017 """
3018 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
3018 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
3019 other = hg.repository(hg.remoteui(repo, opts), source)
3019 other = hg.repository(hg.remoteui(repo, opts), source)
3020 ui.status(_('pulling from %s\n') % url.hidepassword(source))
3020 ui.status(_('pulling from %s\n') % util.hidepassword(source))
3021 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
3021 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
3022
3022
3023 if opts.get('bookmark'):
3023 if opts.get('bookmark'):
@@ -3100,7 +3100,7 b' def push(ui, repo, dest=None, **opts):'
3100
3100
3101 dest = ui.expandpath(dest or 'default-push', dest or 'default')
3101 dest = ui.expandpath(dest or 'default-push', dest or 'default')
3102 dest, branches = hg.parseurl(dest, opts.get('branch'))
3102 dest, branches = hg.parseurl(dest, opts.get('branch'))
3103 ui.status(_('pushing to %s\n') % url.hidepassword(dest))
3103 ui.status(_('pushing to %s\n') % util.hidepassword(dest))
3104 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
3104 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
3105 other = hg.repository(hg.remoteui(repo, opts), dest)
3105 other = hg.repository(hg.remoteui(repo, opts), dest)
3106 if revs:
3106 if revs:
@@ -3919,7 +3919,7 b' def summary(ui, repo, **opts):'
3919 source, branches = hg.parseurl(ui.expandpath('default'))
3919 source, branches = hg.parseurl(ui.expandpath('default'))
3920 other = hg.repository(hg.remoteui(repo, {}), source)
3920 other = hg.repository(hg.remoteui(repo, {}), source)
3921 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
3921 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
3922 ui.debug('comparing with %s\n' % url.hidepassword(source))
3922 ui.debug('comparing with %s\n' % util.hidepassword(source))
3923 repo.ui.pushbuffer()
3923 repo.ui.pushbuffer()
3924 common, incoming, rheads = discovery.findcommonincoming(repo, other)
3924 common, incoming, rheads = discovery.findcommonincoming(repo, other)
3925 repo.ui.popbuffer()
3925 repo.ui.popbuffer()
@@ -3929,7 +3929,7 b' def summary(ui, repo, **opts):'
3929 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
3929 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
3930 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
3930 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
3931 other = hg.repository(hg.remoteui(repo, {}), dest)
3931 other = hg.repository(hg.remoteui(repo, {}), dest)
3932 ui.debug('comparing with %s\n' % url.hidepassword(dest))
3932 ui.debug('comparing with %s\n' % util.hidepassword(dest))
3933 repo.ui.pushbuffer()
3933 repo.ui.pushbuffer()
3934 common, _anyinc, _heads = discovery.findcommonincoming(repo, other)
3934 common, _anyinc, _heads = discovery.findcommonincoming(repo, other)
3935 repo.ui.popbuffer()
3935 repo.ui.popbuffer()
@@ -11,13 +11,13 b' from lock import release'
11 from node import hex, nullid
11 from node import hex, nullid
12 import localrepo, bundlerepo, httprepo, sshrepo, statichttprepo, bookmarks
12 import localrepo, bundlerepo, httprepo, sshrepo, statichttprepo, bookmarks
13 import lock, util, extensions, error, node
13 import lock, util, extensions, error, node
14 import cmdutil, discovery, url
14 import cmdutil, discovery
15 import merge as mergemod
15 import merge as mergemod
16 import verify as verifymod
16 import verify as verifymod
17 import errno, os, shutil
17 import errno, os, shutil
18
18
19 def _local(path):
19 def _local(path):
20 path = util.expandpath(url.localpath(path))
20 path = util.expandpath(util.localpath(path))
21 return (os.path.isfile(path) and bundlerepo or localrepo)
21 return (os.path.isfile(path) and bundlerepo or localrepo)
22
22
23 def addbranchrevs(lrepo, repo, branches, revs):
23 def addbranchrevs(lrepo, repo, branches, revs):
@@ -54,7 +54,7 b' def addbranchrevs(lrepo, repo, branches,'
54 def parseurl(path, branches=None):
54 def parseurl(path, branches=None):
55 '''parse url#branch, returning (url, (branch, branches))'''
55 '''parse url#branch, returning (url, (branch, branches))'''
56
56
57 u = url.url(path)
57 u = util.url(path)
58 branch = None
58 branch = None
59 if u.fragment:
59 if u.fragment:
60 branch = u.fragment
60 branch = u.fragment
@@ -71,7 +71,7 b' schemes = {'
71 }
71 }
72
72
73 def _lookup(path):
73 def _lookup(path):
74 u = url.url(path)
74 u = util.url(path)
75 scheme = u.scheme or 'file'
75 scheme = u.scheme or 'file'
76 thing = schemes.get(scheme) or schemes['file']
76 thing = schemes.get(scheme) or schemes['file']
77 try:
77 try:
@@ -221,8 +221,8 b' def clone(ui, source, dest=None, pull=Fa'
221 else:
221 else:
222 dest = ui.expandpath(dest)
222 dest = ui.expandpath(dest)
223
223
224 dest = url.localpath(dest)
224 dest = util.localpath(dest)
225 source = url.localpath(source)
225 source = util.localpath(source)
226
226
227 if os.path.exists(dest):
227 if os.path.exists(dest):
228 if not os.path.isdir(dest):
228 if not os.path.isdir(dest):
@@ -248,7 +248,7 b' def clone(ui, source, dest=None, pull=Fa'
248 abspath = origsource
248 abspath = origsource
249 copy = False
249 copy = False
250 if src_repo.cancopy() and islocal(dest):
250 if src_repo.cancopy() and islocal(dest):
251 abspath = os.path.abspath(url.localpath(origsource))
251 abspath = os.path.abspath(util.localpath(origsource))
252 copy = not pull and not rev
252 copy = not pull and not rev
253
253
254 if copy:
254 if copy:
@@ -421,7 +421,7 b' def _incoming(displaychlist, subreporecu'
421 """
421 """
422 source, branches = parseurl(ui.expandpath(source), opts.get('branch'))
422 source, branches = parseurl(ui.expandpath(source), opts.get('branch'))
423 other = repository(remoteui(repo, opts), source)
423 other = repository(remoteui(repo, opts), source)
424 ui.status(_('comparing with %s\n') % url.hidepassword(source))
424 ui.status(_('comparing with %s\n') % util.hidepassword(source))
425 revs, checkout = addbranchrevs(repo, other, branches, opts.get('rev'))
425 revs, checkout = addbranchrevs(repo, other, branches, opts.get('rev'))
426
426
427 if revs:
427 if revs:
@@ -477,7 +477,7 b' def incoming(ui, repo, source, opts):'
477 def _outgoing(ui, repo, dest, opts):
477 def _outgoing(ui, repo, dest, opts):
478 dest = ui.expandpath(dest or 'default-push', dest or 'default')
478 dest = ui.expandpath(dest or 'default-push', dest or 'default')
479 dest, branches = parseurl(dest, opts.get('branch'))
479 dest, branches = parseurl(dest, opts.get('branch'))
480 ui.status(_('comparing with %s\n') % url.hidepassword(dest))
480 ui.status(_('comparing with %s\n') % util.hidepassword(dest))
481 revs, checkout = addbranchrevs(repo, repo, branches, opts.get('rev'))
481 revs, checkout = addbranchrevs(repo, repo, branches, opts.get('rev'))
482 if revs:
482 if revs:
483 revs = [repo.lookup(rev) for rev in revs]
483 revs = [repo.lookup(rev) for rev in revs]
@@ -9,7 +9,7 b''
9 import os, re, time
9 import os, re, time
10 from mercurial.i18n import _
10 from mercurial.i18n import _
11 from mercurial import ui, hg, scmutil, util, templater
11 from mercurial import ui, hg, scmutil, util, templater
12 from mercurial import error, encoding, url
12 from mercurial import error, encoding
13 from common import ErrorResponse, get_mtime, staticfile, paritygen, \
13 from common import ErrorResponse, get_mtime, staticfile, paritygen, \
14 get_contact, HTTP_OK, HTTP_NOT_FOUND, HTTP_SERVER_ERROR
14 get_contact, HTTP_OK, HTTP_NOT_FOUND, HTTP_SERVER_ERROR
15 from hgweb_mod import hgweb
15 from hgweb_mod import hgweb
@@ -364,7 +364,7 b' class hgwebdir(object):'
364
364
365 def updatereqenv(self, env):
365 def updatereqenv(self, env):
366 if self._baseurl is not None:
366 if self._baseurl is not None:
367 u = url.url(self._baseurl)
367 u = util.url(self._baseurl)
368 env['SERVER_NAME'] = u.host
368 env['SERVER_NAME'] = u.host
369 if u.port:
369 if u.port:
370 env['SERVER_PORT'] = u.port
370 env['SERVER_PORT'] = u.port
@@ -28,7 +28,7 b' class httprepository(wireproto.wirerepos'
28 self.path = path
28 self.path = path
29 self.caps = None
29 self.caps = None
30 self.handler = None
30 self.handler = None
31 u = url.url(path)
31 u = util.url(path)
32 if u.query or u.fragment:
32 if u.query or u.fragment:
33 raise util.Abort(_('unsupported URL component: "%s"') %
33 raise util.Abort(_('unsupported URL component: "%s"') %
34 (u.query or u.fragment))
34 (u.query or u.fragment))
@@ -111,12 +111,12 b' class httprepository(wireproto.wirerepos'
111 except AttributeError:
111 except AttributeError:
112 proto = resp.headers['content-type']
112 proto = resp.headers['content-type']
113
113
114 safeurl = url.hidepassword(self._url)
114 safeurl = util.hidepassword(self._url)
115 # accept old "text/plain" and "application/hg-changegroup" for now
115 # accept old "text/plain" and "application/hg-changegroup" for now
116 if not (proto.startswith('application/mercurial-') or
116 if not (proto.startswith('application/mercurial-') or
117 proto.startswith('text/plain') or
117 proto.startswith('text/plain') or
118 proto.startswith('application/hg-changegroup')):
118 proto.startswith('application/hg-changegroup')):
119 self.ui.debug("requested URL: '%s'\n" % url.hidepassword(cu))
119 self.ui.debug("requested URL: '%s'\n" % util.hidepassword(cu))
120 raise error.RepoError(
120 raise error.RepoError(
121 _("'%s' does not appear to be an hg repository:\n"
121 _("'%s' does not appear to be an hg repository:\n"
122 "---%%<--- (%s)\n%s\n---%%<---\n")
122 "---%%<--- (%s)\n%s\n---%%<---\n")
@@ -14,7 +14,6 b' import scmutil, util, extensions, hook, '
14 import match as matchmod
14 import match as matchmod
15 import merge as mergemod
15 import merge as mergemod
16 import tags as tagsmod
16 import tags as tagsmod
17 import url as urlmod
18 from lock import release
17 from lock import release
19 import weakref, errno, os, time, inspect
18 import weakref, errno, os, time, inspect
20 propertycache = util.propertycache
19 propertycache = util.propertycache
@@ -1695,7 +1694,7 b' class localrepository(repo.repository):'
1695 cl.delayupdate()
1694 cl.delayupdate()
1696 oldheads = cl.heads()
1695 oldheads = cl.heads()
1697
1696
1698 tr = self.transaction("\n".join([srctype, urlmod.hidepassword(url)]))
1697 tr = self.transaction("\n".join([srctype, util.hidepassword(url)]))
1699 try:
1698 try:
1700 trp = weakref.proxy(tr)
1699 trp = weakref.proxy(tr)
1701 # pull off the changeset group
1700 # pull off the changeset group
@@ -1937,7 +1936,7 b' def aftertrans(files):'
1937 return a
1936 return a
1938
1937
1939 def instance(ui, path, create):
1938 def instance(ui, path, create):
1940 return localrepository(ui, urlmod.localpath(path), create)
1939 return localrepository(ui, util.localpath(path), create)
1941
1940
1942 def islocal(path):
1941 def islocal(path):
1943 return True
1942 return True
@@ -6,7 +6,7 b''
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from i18n import _
8 from i18n import _
9 import util, error, wireproto, url
9 import util, error, wireproto
10
10
11 class remotelock(object):
11 class remotelock(object):
12 def __init__(self, repo):
12 def __init__(self, repo):
@@ -23,7 +23,7 b' class sshrepository(wireproto.wirereposi'
23 self._url = path
23 self._url = path
24 self.ui = ui
24 self.ui = ui
25
25
26 u = url.url(path, parsequery=False, parsefragment=False)
26 u = util.url(path, parsequery=False, parsefragment=False)
27 if u.scheme != 'ssh' or not u.host or u.path is None:
27 if u.scheme != 'ssh' or not u.host or u.path is None:
28 self._abort(error.RepoError(_("couldn't parse location %s") % path))
28 self._abort(error.RepoError(_("couldn't parse location %s") % path))
29
29
@@ -85,7 +85,7 b' class statichttprepository(localrepo.loc'
85 self.ui = ui
85 self.ui = ui
86
86
87 self.root = path
87 self.root = path
88 u = url.url(path.rstrip('/') + "/.hg")
88 u = util.url(path.rstrip('/') + "/.hg")
89 self.path, authinfo = u.authinfo()
89 self.path, authinfo = u.authinfo()
90
90
91 opener = build_opener(ui, authinfo)
91 opener = build_opener(ui, authinfo)
@@ -8,7 +8,7 b''
8 import errno, os, re, xml.dom.minidom, shutil, posixpath
8 import errno, os, re, xml.dom.minidom, shutil, posixpath
9 import stat, subprocess, tarfile
9 import stat, subprocess, tarfile
10 from i18n import _
10 from i18n import _
11 import config, scmutil, util, node, error, cmdutil, url, bookmarks
11 import config, scmutil, util, node, error, cmdutil, bookmarks
12 hg = None
12 hg = None
13 propertycache = util.propertycache
13 propertycache = util.propertycache
14
14
@@ -194,13 +194,13 b' def _abssource(repo, push=False, abort=T'
194 """return pull/push path of repo - either based on parent repo .hgsub info
194 """return pull/push path of repo - either based on parent repo .hgsub info
195 or on the top repo config. Abort or return None if no source found."""
195 or on the top repo config. Abort or return None if no source found."""
196 if hasattr(repo, '_subparent'):
196 if hasattr(repo, '_subparent'):
197 source = url.url(repo._subsource)
197 source = util.url(repo._subsource)
198 source.path = posixpath.normpath(source.path)
198 source.path = posixpath.normpath(source.path)
199 if posixpath.isabs(source.path) or source.scheme:
199 if posixpath.isabs(source.path) or source.scheme:
200 return str(source)
200 return str(source)
201 parent = _abssource(repo._subparent, push, abort=False)
201 parent = _abssource(repo._subparent, push, abort=False)
202 if parent:
202 if parent:
203 parent = url.url(parent)
203 parent = util.url(parent)
204 parent.path = posixpath.join(parent.path, source.path)
204 parent.path = posixpath.join(parent.path, source.path)
205 parent.path = posixpath.normpath(parent.path)
205 parent.path = posixpath.normpath(parent.path)
206 return str(parent)
206 return str(parent)
@@ -7,7 +7,7 b''
7
7
8 from i18n import _
8 from i18n import _
9 import errno, getpass, os, socket, sys, tempfile, traceback
9 import errno, getpass, os, socket, sys, tempfile, traceback
10 import config, scmutil, util, error, url
10 import config, scmutil, util, error
11
11
12 class ui(object):
12 class ui(object):
13 def __init__(self, src=None):
13 def __init__(self, src=None):
@@ -111,7 +111,7 b' class ui(object):'
111 % (n, p, self.configsource('paths', n)))
111 % (n, p, self.configsource('paths', n)))
112 p = p.replace('%%', '%')
112 p = p.replace('%%', '%')
113 p = util.expandpath(p)
113 p = util.expandpath(p)
114 if not url.hasscheme(p) and not os.path.isabs(p):
114 if not util.hasscheme(p) and not os.path.isabs(p):
115 p = os.path.normpath(os.path.join(root, p))
115 p = os.path.normpath(os.path.join(root, p))
116 c.set("paths", n, p)
116 c.set("paths", n, p)
117
117
@@ -332,7 +332,7 b' class ui(object):'
332
332
333 def expandpath(self, loc, default=None):
333 def expandpath(self, loc, default=None):
334 """Return repository location relative to cwd or from [paths]"""
334 """Return repository location relative to cwd or from [paths]"""
335 if url.hasscheme(loc) or os.path.isdir(os.path.join(loc, '.hg')):
335 if util.hasscheme(loc) or os.path.isdir(os.path.join(loc, '.hg')):
336 return loc
336 return loc
337
337
338 path = self.config('paths', loc)
338 path = self.config('paths', loc)
@@ -7,273 +7,11 b''
7 # This software may be used and distributed according to the terms of the
7 # This software may be used and distributed according to the terms of the
8 # GNU General Public License version 2 or any later version.
8 # GNU General Public License version 2 or any later version.
9
9
10 import urllib, urllib2, httplib, os, socket, cStringIO, re
10 import urllib, urllib2, httplib, os, socket, cStringIO
11 import __builtin__
11 import __builtin__
12 from i18n import _
12 from i18n import _
13 import keepalive, util
13 import keepalive, util
14
14
15 class url(object):
16 """Reliable URL parser.
17
18 This parses URLs and provides attributes for the following
19 components:
20
21 <scheme>://<user>:<passwd>@<host>:<port>/<path>?<query>#<fragment>
22
23 Missing components are set to None. The only exception is
24 fragment, which is set to '' if present but empty.
25
26 If parsefragment is False, fragment is included in query. If
27 parsequery is False, query is included in path. If both are
28 False, both fragment and query are included in path.
29
30 See http://www.ietf.org/rfc/rfc2396.txt for more information.
31
32 Note that for backward compatibility reasons, bundle URLs do not
33 take host names. That means 'bundle://../' has a path of '../'.
34
35 Examples:
36
37 >>> url('http://www.ietf.org/rfc/rfc2396.txt')
38 <url scheme: 'http', host: 'www.ietf.org', path: 'rfc/rfc2396.txt'>
39 >>> url('ssh://[::1]:2200//home/joe/repo')
40 <url scheme: 'ssh', host: '[::1]', port: '2200', path: '/home/joe/repo'>
41 >>> url('file:///home/joe/repo')
42 <url scheme: 'file', path: '/home/joe/repo'>
43 >>> url('bundle:foo')
44 <url scheme: 'bundle', path: 'foo'>
45 >>> url('bundle://../foo')
46 <url scheme: 'bundle', path: '../foo'>
47 >>> url('c:\\\\foo\\\\bar')
48 <url path: 'c:\\\\foo\\\\bar'>
49
50 Authentication credentials:
51
52 >>> url('ssh://joe:xyz@x/repo')
53 <url scheme: 'ssh', user: 'joe', passwd: 'xyz', host: 'x', path: 'repo'>
54 >>> url('ssh://joe@x/repo')
55 <url scheme: 'ssh', user: 'joe', host: 'x', path: 'repo'>
56
57 Query strings and fragments:
58
59 >>> url('http://host/a?b#c')
60 <url scheme: 'http', host: 'host', path: 'a', query: 'b', fragment: 'c'>
61 >>> url('http://host/a?b#c', parsequery=False, parsefragment=False)
62 <url scheme: 'http', host: 'host', path: 'a?b#c'>
63 """
64
65 _safechars = "!~*'()+"
66 _safepchars = "/!~*'()+"
67 _matchscheme = re.compile(r'^[a-zA-Z0-9+.\-]+:').match
68
69 def __init__(self, path, parsequery=True, parsefragment=True):
70 # We slowly chomp away at path until we have only the path left
71 self.scheme = self.user = self.passwd = self.host = None
72 self.port = self.path = self.query = self.fragment = None
73 self._localpath = True
74 self._hostport = ''
75 self._origpath = path
76
77 # special case for Windows drive letters
78 if hasdriveletter(path):
79 self.path = path
80 return
81
82 # For compatibility reasons, we can't handle bundle paths as
83 # normal URLS
84 if path.startswith('bundle:'):
85 self.scheme = 'bundle'
86 path = path[7:]
87 if path.startswith('//'):
88 path = path[2:]
89 self.path = path
90 return
91
92 if self._matchscheme(path):
93 parts = path.split(':', 1)
94 if parts[0]:
95 self.scheme, path = parts
96 self._localpath = False
97
98 if not path:
99 path = None
100 if self._localpath:
101 self.path = ''
102 return
103 else:
104 if parsefragment and '#' in path:
105 path, self.fragment = path.split('#', 1)
106 if not path:
107 path = None
108 if self._localpath:
109 self.path = path
110 return
111
112 if parsequery and '?' in path:
113 path, self.query = path.split('?', 1)
114 if not path:
115 path = None
116 if not self.query:
117 self.query = None
118
119 # // is required to specify a host/authority
120 if path and path.startswith('//'):
121 parts = path[2:].split('/', 1)
122 if len(parts) > 1:
123 self.host, path = parts
124 path = path
125 else:
126 self.host = parts[0]
127 path = None
128 if not self.host:
129 self.host = None
130 if path:
131 path = '/' + path
132
133 if self.host and '@' in self.host:
134 self.user, self.host = self.host.rsplit('@', 1)
135 if ':' in self.user:
136 self.user, self.passwd = self.user.split(':', 1)
137 if not self.host:
138 self.host = None
139
140 # Don't split on colons in IPv6 addresses without ports
141 if (self.host and ':' in self.host and
142 not (self.host.startswith('[') and self.host.endswith(']'))):
143 self._hostport = self.host
144 self.host, self.port = self.host.rsplit(':', 1)
145 if not self.host:
146 self.host = None
147
148 if (self.host and self.scheme == 'file' and
149 self.host not in ('localhost', '127.0.0.1', '[::1]')):
150 raise util.Abort(_('file:// URLs can only refer to localhost'))
151
152 self.path = path
153
154 for a in ('user', 'passwd', 'host', 'port',
155 'path', 'query', 'fragment'):
156 v = getattr(self, a)
157 if v is not None:
158 setattr(self, a, urllib.unquote(v))
159
160 def __repr__(self):
161 attrs = []
162 for a in ('scheme', 'user', 'passwd', 'host', 'port', 'path',
163 'query', 'fragment'):
164 v = getattr(self, a)
165 if v is not None:
166 attrs.append('%s: %r' % (a, v))
167 return '<url %s>' % ', '.join(attrs)
168
169 def __str__(self):
170 """Join the URL's components back into a URL string.
171
172 Examples:
173
174 >>> str(url('http://user:pw@host:80/?foo#bar'))
175 'http://user:pw@host:80/?foo#bar'
176 >>> str(url('ssh://user:pw@[::1]:2200//home/joe#'))
177 'ssh://user:pw@[::1]:2200//home/joe#'
178 >>> str(url('http://localhost:80//'))
179 'http://localhost:80//'
180 >>> str(url('http://localhost:80/'))
181 'http://localhost:80/'
182 >>> str(url('http://localhost:80'))
183 'http://localhost:80/'
184 >>> str(url('bundle:foo'))
185 'bundle:foo'
186 >>> str(url('bundle://../foo'))
187 'bundle:../foo'
188 >>> str(url('path'))
189 'path'
190 """
191 if self._localpath:
192 s = self.path
193 if self.scheme == 'bundle':
194 s = 'bundle:' + s
195 if self.fragment:
196 s += '#' + self.fragment
197 return s
198
199 s = self.scheme + ':'
200 if (self.user or self.passwd or self.host or
201 self.scheme and not self.path):
202 s += '//'
203 if self.user:
204 s += urllib.quote(self.user, safe=self._safechars)
205 if self.passwd:
206 s += ':' + urllib.quote(self.passwd, safe=self._safechars)
207 if self.user or self.passwd:
208 s += '@'
209 if self.host:
210 if not (self.host.startswith('[') and self.host.endswith(']')):
211 s += urllib.quote(self.host)
212 else:
213 s += self.host
214 if self.port:
215 s += ':' + urllib.quote(self.port)
216 if self.host:
217 s += '/'
218 if self.path:
219 s += urllib.quote(self.path, safe=self._safepchars)
220 if self.query:
221 s += '?' + urllib.quote(self.query, safe=self._safepchars)
222 if self.fragment is not None:
223 s += '#' + urllib.quote(self.fragment, safe=self._safepchars)
224 return s
225
226 def authinfo(self):
227 user, passwd = self.user, self.passwd
228 try:
229 self.user, self.passwd = None, None
230 s = str(self)
231 finally:
232 self.user, self.passwd = user, passwd
233 if not self.user:
234 return (s, None)
235 return (s, (None, (str(self), self.host),
236 self.user, self.passwd or ''))
237
238 def localpath(self):
239 if self.scheme == 'file' or self.scheme == 'bundle':
240 path = self.path or '/'
241 # For Windows, we need to promote hosts containing drive
242 # letters to paths with drive letters.
243 if hasdriveletter(self._hostport):
244 path = self._hostport + '/' + self.path
245 elif self.host is not None and self.path:
246 path = '/' + path
247 # We also need to handle the case of file:///C:/, which
248 # should return C:/, not /C:/.
249 elif hasdriveletter(path):
250 # Strip leading slash from paths with drive names
251 return path[1:]
252 return path
253 return self._origpath
254
255 def hasscheme(path):
256 return bool(url(path).scheme)
257
258 def hasdriveletter(path):
259 return path[1:2] == ':' and path[0:1].isalpha()
260
261 def localpath(path):
262 return url(path, parsequery=False, parsefragment=False).localpath()
263
264 def hidepassword(u):
265 '''hide user credential in a url string'''
266 u = url(u)
267 if u.passwd:
268 u.passwd = '***'
269 return str(u)
270
271 def removeauth(u):
272 '''remove all authentication information from a url string'''
273 u = url(u)
274 u.user = u.passwd = None
275 return str(u)
276
277 def readauthforuri(ui, uri):
15 def readauthforuri(ui, uri):
278 # Read configuration
16 # Read configuration
279 config = dict()
17 config = dict()
@@ -357,7 +95,7 b' class proxyhandler(urllib2.ProxyHandler)'
357 if not (proxyurl.startswith('http:') or
95 if not (proxyurl.startswith('http:') or
358 proxyurl.startswith('https:')):
96 proxyurl.startswith('https:')):
359 proxyurl = 'http://' + proxyurl + '/'
97 proxyurl = 'http://' + proxyurl + '/'
360 proxy = url(proxyurl)
98 proxy = util.url(proxyurl)
361 if not proxy.user:
99 if not proxy.user:
362 proxy.user = ui.config("http_proxy", "user")
100 proxy.user = ui.config("http_proxy", "user")
363 proxy.passwd = ui.config("http_proxy", "passwd")
101 proxy.passwd = ui.config("http_proxy", "passwd")
@@ -545,7 +283,7 b' def _generic_start_transaction(handler, '
545 new_tunnel = False
283 new_tunnel = False
546
284
547 if new_tunnel or tunnel_host == req.get_full_url(): # has proxy
285 if new_tunnel or tunnel_host == req.get_full_url(): # has proxy
548 u = url(tunnel_host)
286 u = util.url(tunnel_host)
549 if new_tunnel or u.scheme == 'https': # only use CONNECT for HTTPS
287 if new_tunnel or u.scheme == 'https': # only use CONNECT for HTTPS
550 h.realhostport = ':'.join([u.host, (u.port or '443')])
288 h.realhostport = ':'.join([u.host, (u.port or '443')])
551 h.headers = req.headers.copy()
289 h.headers = req.headers.copy()
@@ -876,7 +614,7 b' def opener(ui, authinfo=None):'
876 return opener
614 return opener
877
615
878 def open(ui, url_, data=None):
616 def open(ui, url_, data=None):
879 u = url(url_)
617 u = util.url(url_)
880 if u.scheme:
618 if u.scheme:
881 u.scheme = u.scheme.lower()
619 u.scheme = u.scheme.lower()
882 url_, authinfo = u.authinfo()
620 url_, authinfo = u.authinfo()
@@ -17,7 +17,7 b' from i18n import _'
17 import error, osutil, encoding
17 import error, osutil, encoding
18 import errno, re, shutil, sys, tempfile, traceback
18 import errno, re, shutil, sys, tempfile, traceback
19 import os, time, calendar, textwrap, unicodedata, signal
19 import os, time, calendar, textwrap, unicodedata, signal
20 import imp, socket
20 import imp, socket, urllib
21
21
22 # Python compatibility
22 # Python compatibility
23
23
@@ -1283,3 +1283,265 b' def parsebool(s):'
1283 If s is not a valid boolean, returns None.
1283 If s is not a valid boolean, returns None.
1284 """
1284 """
1285 return _booleans.get(s.lower(), None)
1285 return _booleans.get(s.lower(), None)
1286
1287 class url(object):
1288 """Reliable URL parser.
1289
1290 This parses URLs and provides attributes for the following
1291 components:
1292
1293 <scheme>://<user>:<passwd>@<host>:<port>/<path>?<query>#<fragment>
1294
1295 Missing components are set to None. The only exception is
1296 fragment, which is set to '' if present but empty.
1297
1298 If parsefragment is False, fragment is included in query. If
1299 parsequery is False, query is included in path. If both are
1300 False, both fragment and query are included in path.
1301
1302 See http://www.ietf.org/rfc/rfc2396.txt for more information.
1303
1304 Note that for backward compatibility reasons, bundle URLs do not
1305 take host names. That means 'bundle://../' has a path of '../'.
1306
1307 Examples:
1308
1309 >>> url('http://www.ietf.org/rfc/rfc2396.txt')
1310 <url scheme: 'http', host: 'www.ietf.org', path: 'rfc/rfc2396.txt'>
1311 >>> url('ssh://[::1]:2200//home/joe/repo')
1312 <url scheme: 'ssh', host: '[::1]', port: '2200', path: '/home/joe/repo'>
1313 >>> url('file:///home/joe/repo')
1314 <url scheme: 'file', path: '/home/joe/repo'>
1315 >>> url('bundle:foo')
1316 <url scheme: 'bundle', path: 'foo'>
1317 >>> url('bundle://../foo')
1318 <url scheme: 'bundle', path: '../foo'>
1319 >>> url('c:\\\\foo\\\\bar')
1320 <url path: 'c:\\\\foo\\\\bar'>
1321
1322 Authentication credentials:
1323
1324 >>> url('ssh://joe:xyz@x/repo')
1325 <url scheme: 'ssh', user: 'joe', passwd: 'xyz', host: 'x', path: 'repo'>
1326 >>> url('ssh://joe@x/repo')
1327 <url scheme: 'ssh', user: 'joe', host: 'x', path: 'repo'>
1328
1329 Query strings and fragments:
1330
1331 >>> url('http://host/a?b#c')
1332 <url scheme: 'http', host: 'host', path: 'a', query: 'b', fragment: 'c'>
1333 >>> url('http://host/a?b#c', parsequery=False, parsefragment=False)
1334 <url scheme: 'http', host: 'host', path: 'a?b#c'>
1335 """
1336
1337 _safechars = "!~*'()+"
1338 _safepchars = "/!~*'()+"
1339 _matchscheme = re.compile(r'^[a-zA-Z0-9+.\-]+:').match
1340
1341 def __init__(self, path, parsequery=True, parsefragment=True):
1342 # We slowly chomp away at path until we have only the path left
1343 self.scheme = self.user = self.passwd = self.host = None
1344 self.port = self.path = self.query = self.fragment = None
1345 self._localpath = True
1346 self._hostport = ''
1347 self._origpath = path
1348
1349 # special case for Windows drive letters
1350 if hasdriveletter(path):
1351 self.path = path
1352 return
1353
1354 # For compatibility reasons, we can't handle bundle paths as
1355 # normal URLS
1356 if path.startswith('bundle:'):
1357 self.scheme = 'bundle'
1358 path = path[7:]
1359 if path.startswith('//'):
1360 path = path[2:]
1361 self.path = path
1362 return
1363
1364 if self._matchscheme(path):
1365 parts = path.split(':', 1)
1366 if parts[0]:
1367 self.scheme, path = parts
1368 self._localpath = False
1369
1370 if not path:
1371 path = None
1372 if self._localpath:
1373 self.path = ''
1374 return
1375 else:
1376 if parsefragment and '#' in path:
1377 path, self.fragment = path.split('#', 1)
1378 if not path:
1379 path = None
1380 if self._localpath:
1381 self.path = path
1382 return
1383
1384 if parsequery and '?' in path:
1385 path, self.query = path.split('?', 1)
1386 if not path:
1387 path = None
1388 if not self.query:
1389 self.query = None
1390
1391 # // is required to specify a host/authority
1392 if path and path.startswith('//'):
1393 parts = path[2:].split('/', 1)
1394 if len(parts) > 1:
1395 self.host, path = parts
1396 path = path
1397 else:
1398 self.host = parts[0]
1399 path = None
1400 if not self.host:
1401 self.host = None
1402 if path:
1403 path = '/' + path
1404
1405 if self.host and '@' in self.host:
1406 self.user, self.host = self.host.rsplit('@', 1)
1407 if ':' in self.user:
1408 self.user, self.passwd = self.user.split(':', 1)
1409 if not self.host:
1410 self.host = None
1411
1412 # Don't split on colons in IPv6 addresses without ports
1413 if (self.host and ':' in self.host and
1414 not (self.host.startswith('[') and self.host.endswith(']'))):
1415 self._hostport = self.host
1416 self.host, self.port = self.host.rsplit(':', 1)
1417 if not self.host:
1418 self.host = None
1419
1420 if (self.host and self.scheme == 'file' and
1421 self.host not in ('localhost', '127.0.0.1', '[::1]')):
1422 raise Abort(_('file:// URLs can only refer to localhost'))
1423
1424 self.path = path
1425
1426 for a in ('user', 'passwd', 'host', 'port',
1427 'path', 'query', 'fragment'):
1428 v = getattr(self, a)
1429 if v is not None:
1430 setattr(self, a, urllib.unquote(v))
1431
1432 def __repr__(self):
1433 attrs = []
1434 for a in ('scheme', 'user', 'passwd', 'host', 'port', 'path',
1435 'query', 'fragment'):
1436 v = getattr(self, a)
1437 if v is not None:
1438 attrs.append('%s: %r' % (a, v))
1439 return '<url %s>' % ', '.join(attrs)
1440
1441 def __str__(self):
1442 """Join the URL's components back into a URL string.
1443
1444 Examples:
1445
1446 >>> str(url('http://user:pw@host:80/?foo#bar'))
1447 'http://user:pw@host:80/?foo#bar'
1448 >>> str(url('ssh://user:pw@[::1]:2200//home/joe#'))
1449 'ssh://user:pw@[::1]:2200//home/joe#'
1450 >>> str(url('http://localhost:80//'))
1451 'http://localhost:80//'
1452 >>> str(url('http://localhost:80/'))
1453 'http://localhost:80/'
1454 >>> str(url('http://localhost:80'))
1455 'http://localhost:80/'
1456 >>> str(url('bundle:foo'))
1457 'bundle:foo'
1458 >>> str(url('bundle://../foo'))
1459 'bundle:../foo'
1460 >>> str(url('path'))
1461 'path'
1462 """
1463 if self._localpath:
1464 s = self.path
1465 if self.scheme == 'bundle':
1466 s = 'bundle:' + s
1467 if self.fragment:
1468 s += '#' + self.fragment
1469 return s
1470
1471 s = self.scheme + ':'
1472 if (self.user or self.passwd or self.host or
1473 self.scheme and not self.path):
1474 s += '//'
1475 if self.user:
1476 s += urllib.quote(self.user, safe=self._safechars)
1477 if self.passwd:
1478 s += ':' + urllib.quote(self.passwd, safe=self._safechars)
1479 if self.user or self.passwd:
1480 s += '@'
1481 if self.host:
1482 if not (self.host.startswith('[') and self.host.endswith(']')):
1483 s += urllib.quote(self.host)
1484 else:
1485 s += self.host
1486 if self.port:
1487 s += ':' + urllib.quote(self.port)
1488 if self.host:
1489 s += '/'
1490 if self.path:
1491 s += urllib.quote(self.path, safe=self._safepchars)
1492 if self.query:
1493 s += '?' + urllib.quote(self.query, safe=self._safepchars)
1494 if self.fragment is not None:
1495 s += '#' + urllib.quote(self.fragment, safe=self._safepchars)
1496 return s
1497
1498 def authinfo(self):
1499 user, passwd = self.user, self.passwd
1500 try:
1501 self.user, self.passwd = None, None
1502 s = str(self)
1503 finally:
1504 self.user, self.passwd = user, passwd
1505 if not self.user:
1506 return (s, None)
1507 return (s, (None, (str(self), self.host),
1508 self.user, self.passwd or ''))
1509
1510 def localpath(self):
1511 if self.scheme == 'file' or self.scheme == 'bundle':
1512 path = self.path or '/'
1513 # For Windows, we need to promote hosts containing drive
1514 # letters to paths with drive letters.
1515 if hasdriveletter(self._hostport):
1516 path = self._hostport + '/' + self.path
1517 elif self.host is not None and self.path:
1518 path = '/' + path
1519 # We also need to handle the case of file:///C:/, which
1520 # should return C:/, not /C:/.
1521 elif hasdriveletter(path):
1522 # Strip leading slash from paths with drive names
1523 return path[1:]
1524 return path
1525 return self._origpath
1526
1527 def hasscheme(path):
1528 return bool(url(path).scheme)
1529
1530 def hasdriveletter(path):
1531 return path[1:2] == ':' and path[0:1].isalpha()
1532
1533 def localpath(path):
1534 return url(path, parsequery=False, parsefragment=False).localpath()
1535
1536 def hidepassword(u):
1537 '''hide user credential in a url string'''
1538 u = url(u)
1539 if u.passwd:
1540 u.passwd = '***'
1541 return str(u)
1542
1543 def removeauth(u):
1544 '''remove all authentication information from a url string'''
1545 u = url(u)
1546 u.user = u.passwd = None
1547 return str(u)
@@ -53,7 +53,7 b' import doctest'
53
53
54 def test_url():
54 def test_url():
55 """
55 """
56 >>> from mercurial.url import url
56 >>> from mercurial.util import url
57
57
58 This tests for edge cases in url.URL's parsing algorithm. Most of
58 This tests for edge cases in url.URL's parsing algorithm. Most of
59 these aren't useful for documentation purposes, so they aren't
59 these aren't useful for documentation purposes, so they aren't
General Comments 0
You need to be logged in to leave comments. Login now