multi-urls: add a boolean suboption that unlock path specification as list
When this option is set, a list of patch can be specifed as value for `[paths]`
entries. For the command who support it, this behave the same as providing
multiple destination of the command line.
Differential Revision: https://phab.mercurial-scm.org/D10452
--- a/mercurial/utils/urlutil.py Thu Apr 15 20:13:29 2021 +0200
+++ b/mercurial/utils/urlutil.py Fri Apr 16 00:16:47 2021 +0200
@@ -20,6 +20,10 @@
urllibcompat,
)
+from . import (
+ stringutil,
+)
+
if pycompat.TYPE_CHECKING:
from typing import (
@@ -639,19 +643,30 @@
home_path = os.path.expanduser(b'~')
- for name, loc in ui.configitems(b'paths', ignoresub=True):
+ for name, value in ui.configitems(b'paths', ignoresub=True):
# No location is the same as not existing.
- if not loc:
+ if not value:
continue
_value, sub_opts = ui.configsuboptions(b'paths', name)
s = ui.configsource(b'paths', name)
- root_key = (name, loc, s)
+ root_key = (name, value, 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)]
+
+ multi_url = sub_opts.get(b'multi-urls')
+ if multi_url is not None and stringutil.parsebool(multi_url):
+ base_locs = stringutil.parselist(value)
+ else:
+ base_locs = [value]
+
+ paths = []
+ for loc in base_locs:
+ 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))
+ p = path(ui, name, rawloc=loc, suboptions=sub_opts)
+ paths.append(p)
+ self[name] = paths
for name, old_paths in sorted(self.items()):
new_paths = []
@@ -750,6 +765,17 @@
return value
+@pathsuboption(b'multi-urls', b'multi_urls')
+def multiurls_pathoption(ui, path, value):
+ res = stringutil.parsebool(value)
+ if res is None:
+ ui.warn(
+ _(b'(paths.%s:multi-urls not a boolean; ignoring)\n') % path.name
+ )
+ res = False
+ return res
+
+
def _chain_path(base_path, ui, paths):
"""return the result of "path://" logic applied on a given path"""
new_paths = []
--- a/tests/test-exchange-multi-source.t Thu Apr 15 20:13:29 2021 +0200
+++ b/tests/test-exchange-multi-source.t Fri Apr 16 00:16:47 2021 +0200
@@ -611,3 +611,177 @@
|
% A 0
+
+Testing multi-path definition
+----------------------------
+
+ $ hg clone main-repo repo-paths --rev 0
+ adding changesets
+ adding manifests
+ adding file changes
+ added 1 changesets with 1 changes to 1 files
+ new changesets 4a2df7238c3b
+ updating to branch default
+ 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ $ cp -R ./branch-E ./branch-E-paths
+ $ cp -R ./branch-G ./branch-G-paths
+ $ cp -R ./branch-H ./branch-H-paths
+ $ cat << EOF >> repo-paths/.hg/hgrc
+ > [paths]
+ > E=../branch-E-paths
+ > G=../branch-G-paths
+ > H=../branch-H-paths
+ > EHG=path://E,path://H,path://G
+ > EHG:multi-urls=yes
+ > GEH=path://G,path://E,path://H
+ > GEH:multi-urls=yes
+ > EOF
+
+Do various operations and verify that order matters
+
+ $ hg -R repo-paths push EHG --force
+ pushing to $TESTTMP/branch-E-paths
+ searching for changes
+ no changes found
+ pushing to $TESTTMP/branch-H-paths
+ searching for changes
+ no changes found
+ pushing to $TESTTMP/branch-G-paths
+ searching for changes
+ no changes found
+ [1]
+ $ hg -R repo-paths push GEH --force
+ pushing to $TESTTMP/branch-G-paths
+ searching for changes
+ no changes found
+ pushing to $TESTTMP/branch-E-paths
+ searching for changes
+ no changes found
+ pushing to $TESTTMP/branch-H-paths
+ searching for changes
+ no changes found
+ [1]
+ $ hg -R repo-paths push EHG GEH --force
+ pushing to $TESTTMP/branch-E-paths
+ searching for changes
+ no changes found
+ pushing to $TESTTMP/branch-H-paths
+ searching for changes
+ no changes found
+ pushing to $TESTTMP/branch-G-paths
+ searching for changes
+ no changes found
+ pushing to $TESTTMP/branch-G-paths
+ searching for changes
+ no changes found
+ pushing to $TESTTMP/branch-E-paths
+ searching for changes
+ no changes found
+ pushing to $TESTTMP/branch-H-paths
+ searching for changes
+ no changes found
+ [1]
+ $ hg -R repo-paths pull EHG
+ pulling from $TESTTMP/branch-E-paths
+ searching for changes
+ adding changesets
+ adding manifests
+ adding file changes
+ added 4 changesets with 4 changes to 4 files
+ new changesets 27547f69f254:a603bfb5a83e
+ (run 'hg update' to get a working copy)
+ pulling from $TESTTMP/branch-H-paths
+ searching for changes
+ adding changesets
+ adding manifests
+ adding file changes
+ added 1 changesets with 1 changes to 1 files (+1 heads)
+ new changesets 40faebb2ec45
+ (run 'hg heads' to see heads, 'hg merge' to merge)
+ pulling from $TESTTMP/branch-G-paths
+ searching for changes
+ adding changesets
+ adding manifests
+ adding file changes
+ added 2 changesets with 2 changes to 2 files (+1 heads)
+ new changesets 2f3a4c5c1417:c521a06b234b
+ (run 'hg heads .' to see heads, 'hg merge' to merge)
+ $ hg -R repo-paths pull GEH
+ pulling from $TESTTMP/branch-G-paths
+ searching for changes
+ no changes found
+ pulling from $TESTTMP/branch-E-paths
+ searching for changes
+ no changes found
+ pulling from $TESTTMP/branch-H-paths
+ searching for changes
+ no changes found
+ $ hg -R repo-paths pull EHG GEH
+ pulling from $TESTTMP/branch-E-paths
+ searching for changes
+ no changes found
+ pulling from $TESTTMP/branch-H-paths
+ searching for changes
+ no changes found
+ pulling from $TESTTMP/branch-G-paths
+ searching for changes
+ no changes found
+ pulling from $TESTTMP/branch-G-paths
+ searching for changes
+ no changes found
+ pulling from $TESTTMP/branch-E-paths
+ searching for changes
+ no changes found
+ pulling from $TESTTMP/branch-H-paths
+ searching for changes
+ no changes found
+ $ hg -R repo-paths push EHG --force
+ pushing to $TESTTMP/branch-E-paths
+ searching for changes
+ adding changesets
+ adding manifests
+ adding file changes
+ added 3 changesets with 3 changes to 3 files (+2 heads)
+ pushing to $TESTTMP/branch-H-paths
+ searching for changes
+ adding changesets
+ adding manifests
+ adding file changes
+ added 4 changesets with 4 changes to 4 files (+2 heads)
+ pushing to $TESTTMP/branch-G-paths
+ searching for changes
+ adding changesets
+ adding manifests
+ adding file changes
+ added 4 changesets with 4 changes to 4 files (+2 heads)
+ $ hg -R repo-paths push GEH --force
+ pushing to $TESTTMP/branch-G-paths
+ searching for changes
+ no changes found
+ pushing to $TESTTMP/branch-E-paths
+ searching for changes
+ no changes found
+ pushing to $TESTTMP/branch-H-paths
+ searching for changes
+ no changes found
+ [1]
+ $ hg -R repo-paths push EHG GEH --force
+ pushing to $TESTTMP/branch-E-paths
+ searching for changes
+ no changes found
+ pushing to $TESTTMP/branch-H-paths
+ searching for changes
+ no changes found
+ pushing to $TESTTMP/branch-G-paths
+ searching for changes
+ no changes found
+ pushing to $TESTTMP/branch-G-paths
+ searching for changes
+ no changes found
+ pushing to $TESTTMP/branch-E-paths
+ searching for changes
+ no changes found
+ pushing to $TESTTMP/branch-H-paths
+ searching for changes
+ no changes found
+ [1]
--- a/tests/test-paths.t Thu Apr 15 20:13:29 2021 +0200
+++ b/tests/test-paths.t Fri Apr 16 00:16:47 2021 +0200
@@ -388,3 +388,128 @@
abort: cannot use `path://unknown`, "unknown" is not a known path
[255]
+Test path pointing to multiple urls
+===================================
+
+Simple cases
+------------
+- one layer
+- one list
+- no special option
+
+ $ cat << EOF > .hg/hgrc
+ > [paths]
+ > one-path=foo
+ > multiple-path=foo,bar,baz,https://example.org/
+ > multiple-path:multi-urls=yes
+ > EOF
+ $ hg path
+ gpath1 = http://hg.example.com/
+ multiple-path = $TESTTMP/chained_path/foo
+ multiple-path:multi-urls = yes
+ multiple-path = $TESTTMP/chained_path/bar
+ multiple-path:multi-urls = yes
+ multiple-path = $TESTTMP/chained_path/baz
+ multiple-path:multi-urls = yes
+ multiple-path = https://example.org/
+ multiple-path:multi-urls = yes
+ one-path = $TESTTMP/chained_path/foo
+
+Reference to a list
+-------------------
+
+ $ cat << EOF >> .hg/hgrc
+ > ref-to-multi=path://multiple-path
+ > EOF
+ $ hg path | grep ref-to-multi
+ ref-to-multi = $TESTTMP/chained_path/foo
+ ref-to-multi:multi-urls = yes
+ ref-to-multi = $TESTTMP/chained_path/bar
+ ref-to-multi:multi-urls = yes
+ ref-to-multi = $TESTTMP/chained_path/baz
+ ref-to-multi:multi-urls = yes
+ ref-to-multi = https://example.org/
+ ref-to-multi:multi-urls = yes
+
+List with a reference
+---------------------
+
+ $ cat << EOF >> .hg/hgrc
+ > multi-with-ref=path://one-path, ssh://babar@savannah/celeste-ville
+ > multi-with-ref:multi-urls=yes
+ > EOF
+ $ hg path | grep multi-with-ref
+ multi-with-ref = $TESTTMP/chained_path/foo
+ multi-with-ref:multi-urls = yes
+ multi-with-ref = ssh://babar@savannah/celeste-ville
+ multi-with-ref:multi-urls = yes
+
+List with a reference to a list
+-------------------------------
+
+ $ cat << EOF >> .hg/hgrc
+ > multi-to-multi-ref = path://multiple-path, ssh://celeste@savannah/celeste-ville
+ > multi-to-multi-ref:multi-urls = yes
+ > EOF
+ $ hg path | grep multi-to-multi-ref
+ multi-to-multi-ref = $TESTTMP/chained_path/foo
+ multi-to-multi-ref:multi-urls = yes
+ multi-to-multi-ref = $TESTTMP/chained_path/bar
+ multi-to-multi-ref:multi-urls = yes
+ multi-to-multi-ref = $TESTTMP/chained_path/baz
+ multi-to-multi-ref:multi-urls = yes
+ multi-to-multi-ref = https://example.org/
+ multi-to-multi-ref:multi-urls = yes
+ multi-to-multi-ref = ssh://celeste@savannah/celeste-ville
+ multi-to-multi-ref:multi-urls = yes
+
+individual suboptions are inherited
+-----------------------------------
+
+ $ cat << EOF >> .hg/hgrc
+ > with-pushurl = foo
+ > with-pushurl:pushurl = http://foo.bar/
+ > with-pushrev = bar
+ > with-pushrev:pushrev = draft()
+ > with-both = toto
+ > with-both:pushurl = http://ta.ta
+ > with-both:pushrev = secret()
+ > ref-all-no-opts = path://with-pushurl, path://with-pushrev, path://with-both
+ > ref-all-no-opts:multi-urls = yes
+ > with-overwrite = path://with-pushurl, path://with-pushrev, path://with-both
+ > with-overwrite:multi-urls = yes
+ > with-overwrite:pushrev = public()
+ > EOF
+ $ hg path | grep with-pushurl
+ with-pushurl = $TESTTMP/chained_path/foo
+ with-pushurl:pushurl = http://foo.bar/
+ $ hg path | grep with-pushrev
+ with-pushrev = $TESTTMP/chained_path/bar
+ with-pushrev:pushrev = draft()
+ $ hg path | grep with-both
+ with-both = $TESTTMP/chained_path/toto
+ with-both:pushrev = secret()
+ with-both:pushurl = http://ta.ta/
+ $ hg path | grep ref-all-no-opts
+ ref-all-no-opts = $TESTTMP/chained_path/foo
+ ref-all-no-opts:multi-urls = yes
+ ref-all-no-opts:pushurl = http://foo.bar/
+ ref-all-no-opts = $TESTTMP/chained_path/bar
+ ref-all-no-opts:multi-urls = yes
+ ref-all-no-opts:pushrev = draft()
+ ref-all-no-opts = $TESTTMP/chained_path/toto
+ ref-all-no-opts:multi-urls = yes
+ ref-all-no-opts:pushrev = secret()
+ ref-all-no-opts:pushurl = http://ta.ta/
+ $ hg path | grep with-overwrite
+ with-overwrite = $TESTTMP/chained_path/foo
+ with-overwrite:multi-urls = yes
+ with-overwrite:pushrev = public()
+ with-overwrite:pushurl = http://foo.bar/
+ with-overwrite = $TESTTMP/chained_path/bar
+ with-overwrite:multi-urls = yes
+ with-overwrite:pushrev = public()
+ with-overwrite = $TESTTMP/chained_path/toto
+ with-overwrite:multi-urls = yes
+ with-overwrite:pushrev = public()
+ with-overwrite:pushurl = http://ta.ta/