[PATCH 1 of 2] ui: move URL and path detection into path API
Gregory Szorc
gregory.szorc at gmail.com
Wed Aug 19 05:07:54 UTC 2015
# HG changeset patch
# User Gregory Szorc <gregory.szorc at gmail.com>
# Date 1439018162 25200
# Sat Aug 08 00:16:02 2015 -0700
# Node ID 1699cd0bac167bd24f710c849d78d6a6c0089ac9
# Parent d9d3d49c4cf77049d12920980e91bf8e4a4ecda2
ui: move URL and path detection into path API
ui.expandpath() has code for recognizing URLs or local filesystem
paths. Our goal is to use ``path`` class instances everywhere a path
is represented.
Changing ui.expandpath() to return path instances is a lot of work.
Our goal is to slowly marginalize it by moving logic into the paths
API and to convert callers to the paths API.
Many callers of ui.expandpath() pass in a value that could be a
local filesystem path or URI. We move the detection of these strings
from ui.expandpath() to paths.getpath() and path.__init__(). To do
this properly in a way that is compatible with future callers, we
need to parse the "#branch" syntax out of locations. This is a bit
complicated, but it is necessary.
The code for URL parsing is essentially a copy of hg.parseurl().
Once all consumers are speaking the paths API, it is likely that
this function won't be called any more and it can be deleted.
diff --git a/mercurial/ui.py b/mercurial/ui.py
--- a/mercurial/ui.py
+++ b/mercurial/ui.py
@@ -549,14 +549,11 @@ class ui(object):
return user
def expandpath(self, loc, default=None):
"""Return repository location relative to cwd or from [paths]"""
- if util.hasscheme(loc) or os.path.isdir(os.path.join(loc, '.hg')):
- return loc
-
p = self.paths.getpath(loc, default=default)
if p:
- return p.loc
+ return p.rawloc
return loc
@util.propertycache
def paths(self):
@@ -1001,16 +998,25 @@ class paths(dict):
continue
self[name] = path(name, rawloc=loc)
def getpath(self, name, default=None):
- """Return a ``path`` for the specified name, falling back to a default.
+ """Return a ``path`` from a string, falling back to a default.
+
+ ``name`` can be a named path or locations. Locations are filesystem
+ paths or URIs.
Returns the first of ``name`` or ``default`` that is present, or None
if neither is present.
"""
try:
return self[name]
except KeyError:
+ # Try to resolve as a local path or URI.
+ try:
+ return path(None, rawloc=name)
+ except ValueError:
+ pass
+
if default is not None:
try:
return self[default]
except KeyError:
@@ -1025,12 +1031,36 @@ class path(object):
"""Construct a path from its config options.
``name`` is the symbolic name of the path.
``rawloc`` is the raw location, as defined in the config.
+
+ If ``name`` is not defined, we require that the location be a) a local
+ filesystem path with a .hg directory or b) a URL. If not,
+ ``ValueError`` is raised.
"""
+ if not rawloc:
+ raise ValueError('rawloc must be defined')
+
+ # Locations may define branches via syntax <base>#<branch>.
+ u = util.url(rawloc)
+ branch = None
+ if u.fragment:
+ branch = u.fragment
+ u.fragment = None
+
+ self.url = u
+ self.branch = branch
+
self.name = name
- # We'll do more intelligent things with rawloc in the future.
- self.loc = rawloc
+ self.rawloc = rawloc
+ self.loc = str(u)
+
+ # When given a raw location but not a symbolic name, validate the
+ # location is valid.
+ if (not name and not u.scheme
+ and not os.path.isdir(os.path.join(str(u), '.hg'))):
+ raise ValueError('location is not a URL or path to a local '
+ 'repo: %s' % rawloc)
# we instantiate one globally shared progress bar to avoid
# competing progress bars when multiple UI objects get created
_progresssingleton = None
More information about the Mercurial-devel
mailing list