Patchwork [5,of,5,paths,v3] ui: move URL and path detection into getpath()

mail settings
Submitter Gregory Szorc
Date March 8, 2015, 7:54 p.m.
Message ID <>
Download mbox | patch
Permalink /patch/7945/
State Changes Requested
Delegated to: Pierre-Yves David
Headers show


Gregory Szorc - March 8, 2015, 7:54 p.m.
# HG changeset patch
# User Gregory Szorc <>
# Date 1423427350 28800
#      Sun Feb 08 12:29:10 2015 -0800
# Node ID 6c3e9b2db9bbe61b474bacb80d4c66baec0cf5d4
# Parent  46c14d03f3e05aa9992d074311c5e92924c2dda3
ui: move URL and path detection into getpath()

ui.expandpath() has code for recognizing URLs or local filesystem
paths. Our goal is to use path instances in more locations. Since many
call sites pass in arguments that could be URLs or filesystem paths,
we move this code into paths.getpath() so that more callers can be
switched to using the new API directly instead of ui.expandpath().

The added check for whether ``name`` is defined is added because
future callers may pass in empty values (expandpath doesn't
appear to receive empty values today).

Upcoming patches will perform additional processing on the "local"
argument to path.__init__. For now, we don't distinguish between the
origin and shoehorn everything into "loc."


diff --git a/mercurial/ b/mercurial/
--- a/mercurial/
+++ b/mercurial/
@@ -528,11 +528,8 @@  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
         if loc == 'default-push':
             p = self.paths.getpath(loc, default=True)
         elif loc == 'default':
             p = self.paths.getpath(loc)
@@ -957,15 +954,19 @@  class paths(dict):
             self[name] = path(name, rawloc=loc)
     def getpath(self, name, default=False):
-        """Return a ``path`` for the specified name, falling back to a default.
+        """Return a ``path`` from a string.
+        Arguments can be named paths (from the config) or locations. Locations
+        are URIs or filesystem paths that are directories having ``.hg``
+        directories.
         If ``default`` is True, we attempt to resolve the default path.
         If ``default`` is the string ``push``, we attempt to resolve the
         default push path.
-        Returns ``None`` if a path could not be found.
+        Returns ``None`` if a path could not be resolved.
             return self[name]
         except KeyError:
@@ -983,18 +984,39 @@  class paths(dict):
                 return self['default']
             except KeyError:
+        try:
+            return path(name)
+        except ValueError:
+            pass
         return None
 class path(object):
     """Represents an individual path and its configuration."""
     def __init__(self, name, rawloc=None):
         """Construct a path from its config options.
-        ``name`` is the symbolic name of the path.
+        ``name`` is the symbolic name of the path or location.
         ``rawloc`` is the raw location, as defined in the config.
+        When ``rawloc`` isn't defined, we assume ``name`` is the location.
+        In this form, we require that the location be a local filesystem
+        path to a known repository or a URL. If not, ``ValueError`` is
+        raised.
+        if name and not rawloc:
+            if util.hasscheme(name):
+       = None
+                self.loc = name
+            elif os.path.isdir(os.path.join(name, '.hg')):
+       = name
+                self.loc = name
+            else:
+                raise ValueError('location is not a URL or path to a local '
+                                 'repo: %s' % name)
+            return
+ = name
-        # We'll do more intelligent things with rawloc in the future.
         self.loc = rawloc