Patchwork D10451: urlutil: move url "fixing" at the time of `ui.paths` initialization

login
register
mail settings
Submitter phabricator
Date April 16, 2021, 12:56 a.m.
Message ID <differential-rev-PHID-DREV-uctxlyrfbpzumbyx7toy-req@mercurial-scm.org>
Download mbox | patch
Permalink /patch/48771/
State New
Headers show

Comments

phabricator - April 16, 2021, 12:56 a.m.
marmoute created this revision.
Herald added a reviewer: hg-reviewers.
Herald added a subscriber: mercurial-patches.

REVISION SUMMARY
  Doing such fixing at the time is simpler and will be necessary to deal with
  urls list in a sane manner. It also reduce the size of fix-config which is
  always better.
  
  I wish we could get ride of the hackish way to pass the root around, I suspect
  that the `root` variable could be stored as part of the config value, along side
  the source. However getting to the end of this `root` business is a far too
  large detours to make now.
  
  The test change to `tests/test-hgrc.t` and `test-config.t` are expectied since
  we are not longer altering the config itself, but the way it is interpreted when
  building path.  This seems more correct.
  
  I also added a couple of test call to `test-config.t` and `test-globalopts.t` to
  clarify that the expanding process is properly happening a the right time.

REPOSITORY
  rHG Mercurial

BRANCH
  default

REVISION DETAIL
  https://phab.mercurial-scm.org/D10451

AFFECTED FILES
  mercurial/ui.py
  mercurial/utils/urlutil.py
  tests/test-config.t
  tests/test-globalopts.t
  tests/test-hgrc.t

CHANGE DETAILS




To: marmoute, #hg-reviewers
Cc: mercurial-patches, mercurial-devel

Patch

diff --git a/tests/test-hgrc.t b/tests/test-hgrc.t
--- a/tests/test-hgrc.t
+++ b/tests/test-hgrc.t
@@ -256,7 +256,7 @@ 
   $ hg showconfig --debug paths
   plain: True
   read config from: $TESTTMP/hgrc
-  $TESTTMP/hgrc:17: paths.foo=$TESTTMP/bar
+  $TESTTMP/hgrc:17: paths.foo=bar
 
 Test we can skip the user configuration
 
diff --git a/tests/test-globalopts.t b/tests/test-globalopts.t
--- a/tests/test-globalopts.t
+++ b/tests/test-globalopts.t
@@ -74,6 +74,10 @@ 
   8580ff50825a tip
   $ echo '[paths]' >> $HGRCPATH
   $ echo 'relativetohome = a' >> $HGRCPATH
+  $ hg path | grep relativetohome
+  relativetohome = $TESTTMP/a
+  $ HOME=`pwd`/../ hg path | grep relativetohome
+  relativetohome = $TESTTMP/a
   $ HOME=`pwd`/../ hg -R relativetohome identify
   8580ff50825a tip
   $ cd ..
diff --git a/tests/test-config.t b/tests/test-config.t
--- a/tests/test-config.t
+++ b/tests/test-config.t
@@ -338,8 +338,14 @@ 
   > EOF
 
   $ hg showconfig paths
+  paths.foo=~/foo
   paths.foo:suboption=~/foo
-  paths.foo=$TESTTMP/foo
+
+note: The path expansion no longer happens at the config level, but the path is
+still expanded:
+
+  $ hg path | grep foo
+  foo = $TESTTMP/foo
 
 edit failure
 
diff --git a/mercurial/utils/urlutil.py b/mercurial/utils/urlutil.py
--- a/mercurial/utils/urlutil.py
+++ b/mercurial/utils/urlutil.py
@@ -635,11 +635,20 @@ 
     def __init__(self, ui):
         dict.__init__(self)
 
+        home_path = os.path.expanduser(b'~')
+
         for name, loc in ui.configitems(b'paths', ignoresub=True):
             # No location is the same as not existing.
             if not loc:
                 continue
-            loc, sub_opts = ui.configsuboptions(b'paths', name)
+            _value, sub_opts = ui.configsuboptions(b'paths', name)
+            s = ui.configsource(b'paths', name)
+            root_key = (name, loc, s)
+            root = ui._path_to_root.get(root_key, home_path)
+            loc = os.path.expandvars(loc)
+            loc = os.path.expanduser(loc)
+            if not hasscheme(loc) and not os.path.isabs(loc):
+                loc = os.path.normpath(os.path.join(root, loc))
             self[name] = [path(ui, name, rawloc=loc, suboptions=sub_opts)]
 
         for name, old_paths in sorted(self.items()):
diff --git a/mercurial/ui.py b/mercurial/ui.py
--- a/mercurial/ui.py
+++ b/mercurial/ui.py
@@ -234,6 +234,8 @@ 
         self._trustusers = set()
         self._trustgroups = set()
         self.callhooks = True
+        # old the root to use for each [paths] entry
+        self._path_to_root = {}
         # Insecure server connections requested.
         self.insecureconnections = False
         # Blocked time
@@ -265,6 +267,7 @@ 
             self._trustgroups = src._trustgroups.copy()
             self.environ = src.environ
             self.callhooks = src.callhooks
+            self._path_to_root = src._path_to_root
             self.insecureconnections = src.insecureconnections
             self._colormode = src._colormode
             self._terminfoparams = src._terminfoparams.copy()
@@ -546,22 +549,26 @@ 
             root = root or encoding.getcwd()
             for c in self._tcfg, self._ucfg, self._ocfg:
                 for n, p in c.items(b'paths'):
+                    old_p = p
+                    s = self.configsource(b'paths', n) or b'none'
+                    root_key = (n, p, s)
+                    if root_key not in self._path_to_root:
+                        self._path_to_root[root_key] = root
                     # Ignore sub-options.
                     if b':' in n:
                         continue
                     if not p:
                         continue
                     if b'%%' in p:
-                        s = self.configsource(b'paths', n) or b'none'
+                        if s is None:
+                            s = 'none'
                         self.warn(
                             _(b"(deprecated '%%' in path %s=%s from %s)\n")
                             % (n, p, s)
                         )
                         p = p.replace(b'%%', b'%')
-                    p = util.expandpath(p)
-                    if not urlutil.hasscheme(p) and not os.path.isabs(p):
-                        p = os.path.normpath(os.path.join(root, p))
-                    c.alter(b"paths", n, p)
+                    if p != old_p:
+                        c.alter(b"paths", n, p)
 
         if section in (None, b'ui'):
             # update ui options