D10451: urlutil: move url "fixing" at the time of `ui.paths` initialization
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 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' +
D10455: urlutil: provide some information about "bad url" when processing `pushurl`
marmoute created this revision. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REVISION SUMMARY It appears pushurl only support `://` entries. This is not obvious and can lead to obscure error. We make the error less obscure as a start.. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10455 AFFECTED FILES mercurial/utils/urlutil.py tests/test-paths.t CHANGE DETAILS diff --git a/tests/test-paths.t b/tests/test-paths.t --- a/tests/test-paths.t +++ b/tests/test-paths.t @@ -175,7 +175,7 @@ > EOF $ hg paths - (paths.default:pushurl not a URL; ignoring) + (paths.default:pushurl not a URL; ignoring: "/not/a/url") default = /path/to/nothing #fragment is not allowed in :pushurl diff --git a/mercurial/utils/urlutil.py b/mercurial/utils/urlutil.py --- a/mercurial/utils/urlutil.py +++ b/mercurial/utils/urlutil.py @@ -740,7 +740,9 @@ u = url(value) # Actually require a URL. if not u.scheme: -ui.warn(_(b'(paths.%s:pushurl not a URL; ignoring)\n') % path.name) +msg = _(b'(paths.%s:pushurl not a URL; ignoring: "%s")\n') +msg %= (path.name, value) +ui.warn(msg) return None # Don't support the #foo syntax in the push URL to declare branch to To: marmoute, #hg-reviewers Cc: mercurial-patches, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D10454: revset: document the `outgoing` behavior if the path resolve to multiple urls
marmoute created this revision. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10454 AFFECTED FILES mercurial/revset.py CHANGE DETAILS diff --git a/mercurial/revset.py b/mercurial/revset.py --- a/mercurial/revset.py +++ b/mercurial/revset.py @@ -1842,6 +1842,9 @@ def outgoing(repo, subset, x): """Changesets not found in the specified destination repository, or the default push location. + +If the location resolve to multiple repositories, the union of all +outgoing changeset will be used. """ # Avoid cycles. from . import ( To: marmoute, #hg-reviewers Cc: mercurial-patches, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D10452: multi-urls: add a boolean suboption that unlock path specification as list
marmoute created this revision. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REVISION SUMMARY 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. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10452 AFFECTED FILES mercurial/utils/urlutil.py tests/test-exchange-multi-source.t tests/test-paths.t CHANGE DETAILS diff --git a/tests/test-paths.t b/tests/test-paths.t --- a/tests/test-paths.t +++ b/tests/test-paths.t @@ -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/ diff --git a/tests/test-exchange-mu
D10449: parselist: move the function from config to stringutil
marmoute created this revision. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REVISION SUMMARY We move the function in a lower level module to avoid cycle. It moves next to `parsebool` who had to migrate for the same reasons. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10449 AFFECTED FILES mercurial/config.py mercurial/ui.py mercurial/utils/stringutil.py rust/hg-core/src/config/config.rs tests/test-doctest.py CHANGE DETAILS diff --git a/tests/test-doctest.py b/tests/test-doctest.py --- a/tests/test-doctest.py +++ b/tests/test-doctest.py @@ -131,7 +131,6 @@ ('mercurial.changelog', '{}'), ('mercurial.cmdutil', '{}'), ('mercurial.color', '{}'), -('mercurial.config', '{}'), ('mercurial.dagparser', "{'optionflags': 4}"), ('mercurial.encoding', '{}'), ('mercurial.fancyopts', '{}'), diff --git a/rust/hg-core/src/config/config.rs b/rust/hg-core/src/config/config.rs --- a/rust/hg-core/src/config/config.rs +++ b/rust/hg-core/src/config/config.rs @@ -361,10 +361,11 @@ /// /// This is appropriate for new configuration keys. The value syntax is /// **not** the same as most existing list-valued config, which has Python -/// parsing implemented in `parselist()` in `mercurial/config.py`. -/// Faithfully porting that parsing algorithm to Rust (including behavior -/// that are arguably bugs) turned out to be non-trivial and hasn’t been -/// completed as of this writing. +/// parsing implemented in `parselist()` in +/// `mercurial/utils/stringutil.py`. Faithfully porting that parsing +/// algorithm to Rust (including behavior that are arguably bugs) +/// turned out to be non-trivial and hasn’t been completed as of this +/// writing. /// /// Instead, the "simple" syntax is: split on comma, then trim leading and /// trailing whitespace of each component. Quotes or backslashes are not diff --git a/mercurial/utils/stringutil.py b/mercurial/utils/stringutil.py --- a/mercurial/utils/stringutil.py +++ b/mercurial/utils/stringutil.py @@ -868,6 +868,96 @@ return _booleans.get(s.lower(), None) +def parselist(value): +"""parse a configuration value as a list of comma/space separated strings + +>>> parselist(b'this,is "a small" ,test') +['this', 'is', 'a small', 'test'] +""" + +def _parse_plain(parts, s, offset): +whitespace = False +while offset < len(s) and ( +s[offset : offset + 1].isspace() or s[offset : offset + 1] == b',' +): +whitespace = True +offset += 1 +if offset >= len(s): +return None, parts, offset +if whitespace: +parts.append(b'') +if s[offset : offset + 1] == b'"' and not parts[-1]: +return _parse_quote, parts, offset + 1 +elif s[offset : offset + 1] == b'"' and parts[-1][-1:] == b'\\': +parts[-1] = parts[-1][:-1] + s[offset : offset + 1] +return _parse_plain, parts, offset + 1 +parts[-1] += s[offset : offset + 1] +return _parse_plain, parts, offset + 1 + +def _parse_quote(parts, s, offset): +if offset < len(s) and s[offset : offset + 1] == b'"': # "" +parts.append(b'') +offset += 1 +while offset < len(s) and ( +s[offset : offset + 1].isspace() +or s[offset : offset + 1] == b',' +): +offset += 1 +return _parse_plain, parts, offset + +while offset < len(s) and s[offset : offset + 1] != b'"': +if ( +s[offset : offset + 1] == b'\\' +and offset + 1 < len(s) +and s[offset + 1 : offset + 2] == b'"' +): +offset += 1 +parts[-1] += b'"' +else: +parts[-1] += s[offset : offset + 1] +offset += 1 + +if offset >= len(s): +real_parts = _configlist(parts[-1]) +if not real_parts: +parts[-1] = b'"' +else: +real_parts[0] = b'"' + real_parts[0] +parts = parts[:-1] +parts.extend(real_parts) +return None, parts, offset + +offset += 1 +while offset < len(s) and s[offset : offset + 1] in [b' ', b',']: +offset += 1 + +if offset < len(s): +if offset + 1 == len(s) and s[offset : offset + 1] == b'"': +parts[-1] += b'"' +offset += 1 +else: +parts.append(b'') +else: +return None, parts, offset + +return _parse_plain, parts, offset + +def _configlist(s): +s = s.rstrip(b' ,') +if not s: +return [] +parser, parts, offset = _parse_plain, [b''], 0 +while parser
D10453: multi-urls: document the feature
marmoute created this revision. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REVISION SUMMARY We have a feature lets make it visible to people. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10453 AFFECTED FILES mercurial/helptext/config.txt tests/test-help.t CHANGE DETAILS diff --git a/tests/test-help.t b/tests/test-help.t --- a/tests/test-help.t +++ b/tests/test-help.t @@ -1847,6 +1847,12 @@ The following sub-options can be defined: + "multi-urls" + A boolean option. When enabled the value of the '[paths]' entry will be + parsed as a list and the alias will resolve to multiple destination. If + some of the list entry use the 'path://' syntax, the suboption will be + inherited indiviually. + "pushurl" The URL to use for push operations. If not defined, the location defined by the path's main entry is used. diff --git a/mercurial/helptext/config.txt b/mercurial/helptext/config.txt --- a/mercurial/helptext/config.txt +++ b/mercurial/helptext/config.txt @@ -1717,6 +1717,12 @@ The following sub-options can be defined: +``multi-urls`` + A boolean option. When enabled the value of the `[paths]` entry will be + parsed as a list and the alias will resolve to multiple destination. If some + of the list entry use the `path://` syntax, the suboption will be inherited + indiviually. + ``pushurl`` The URL to use for push operations. If not defined, the location defined by the path's main entry is used. To: marmoute, #hg-reviewers Cc: mercurial-patches, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D10450: path: teach the `hg path` command to display boolean sub-option
marmoute created this revision. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REVISION SUMMARY The next changeset introduce one. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10450 AFFECTED FILES mercurial/commands.py CHANGE DETAILS diff --git a/mercurial/commands.py b/mercurial/commands.py --- a/mercurial/commands.py +++ b/mercurial/commands.py @@ -5151,6 +5151,11 @@ assert subopt not in (b'name', b'url') if showsubopts: fm.plain(b'%s:%s = ' % (name, subopt)) +if isinstance(value, bool): +if value: +value = b'yes' +else: +value = b'no' fm.condwrite(showsubopts, subopt, b'%s\n', value) fm.end() To: marmoute, #hg-reviewers Cc: mercurial-patches, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D10448: bookmark: use `list_paths` to access path definition
marmoute created this revision. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REVISION SUMMARY The content of the `[paths]` config section is receiving transformation that make it hard to recognise whats the actual name, and the next changeset will make it worse. So we use the official API for this instead. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10448 AFFECTED FILES mercurial/bookmarks.py CHANGE DETAILS diff --git a/mercurial/bookmarks.py b/mercurial/bookmarks.py --- a/mercurial/bookmarks.py +++ b/mercurial/bookmarks.py @@ -601,11 +601,12 @@ # if an @pathalias already exists, we overwrite (update) it if path.startswith(b"file:"): path = urlutil.url(path).path -for p, u in ui.configitems(b"paths"): -if u.startswith(b"file:"): -u = urlutil.url(u).path -if path == u: -return b'%s@%s' % (b, p) +for name, p in urlutil.list_paths(ui): +loc = p.rawloc +if loc.startswith(b"file:"): +loc = urlutil.url(loc).path +if path == loc: +return b'%s@%s' % (b, name) # assign a unique "@number" suffix newly for x in range(1, 100): To: marmoute, #hg-reviewers Cc: mercurial-patches, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D10447: urlutil: make `paths` class old list of `path`
marmoute created this revision. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REVISION SUMMARY We move from a `{name → path}` mapping to a `{name → [path]}` mapping. And update all user code accordingly. For now, all the list contains exactly one element, but we are now in a good place to make the config understand a list of url. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10447 AFFECTED FILES mercurial/templatekw.py mercurial/utils/urlutil.py CHANGE DETAILS diff --git a/mercurial/utils/urlutil.py b/mercurial/utils/urlutil.py --- a/mercurial/utils/urlutil.py +++ b/mercurial/utils/urlutil.py @@ -447,14 +447,16 @@ def list_paths(ui, target_path=None): """list all the (name, paths) in the passed ui""" +result = [] if target_path is None: -return sorted(pycompat.iteritems(ui.paths)) +for name, paths in sorted(pycompat.iteritems(ui.paths)): +for p in paths: +result.append((name, p)) + else: -path = ui.paths.get(target_path) -if path is None: -return [] -else: -return [(target_path, path)] +for path in ui.paths.get(target_path, []): +result.append((target_path, path)) +return result def try_path(ui, url): @@ -473,9 +475,11 @@ """yields all the `path` selected as push destination by `dests`""" if not dests: if b'default-push' in ui.paths: -yield ui.paths[b'default-push'] +for p in ui.paths[b'default-push']: +yield p elif b'default' in ui.paths: -yield ui.paths[b'default'] +for p in ui.paths[b'default']: +yield p else: raise error.ConfigError( _(b'default repository not configured!'), @@ -484,7 +488,8 @@ else: for dest in dests: if dest in ui.paths: -yield ui.paths[dest] +for p in ui.paths[dest]: +yield p else: path = try_path(ui, dest) if path is None: @@ -500,7 +505,8 @@ sources = [b'default'] for source in sources: if source in ui.paths: -url = ui.paths[source].rawloc +for p in ui.paths[source]: +yield parseurl(p.rawloc, default_branches) else: # Try to resolve as a local path or URI. path = try_path(ui, source) @@ -508,7 +514,7 @@ url = path.rawloc else: url = source -yield parseurl(url, default_branches) +yield parseurl(url, default_branches) def get_unique_push_path(action, repo, ui, dest=None): @@ -526,7 +532,14 @@ else: dests = [dest] dests = list(get_push_paths(repo, ui, dests)) -assert len(dests) == 1 +if len(dests) != 1: +if dest is None: +msg = _("default path point to %d urls while %s only support one") +msg %= (len(dests), action) +else: +msg = _("path point to %d urls while %s only support one: %s") +msg %= (len(dests), action, dest) +raise error.Abort(msg) return dests[0] @@ -540,45 +553,64 @@ The `action` parameter will be used for the error message. """ +urls = [] if source is None: if b'default' in ui.paths: -url = ui.paths[b'default'].rawloc +urls.extend(p.rawloc for p in ui.paths[b'default']) else: # XXX this is the historical default behavior, but that is not # great, consider breaking BC on this. -url = b'default' +urls.append(b'default') else: if source in ui.paths: -url = ui.paths[source].rawloc +urls.extend(p.rawloc for p in ui.paths[source]) else: # Try to resolve as a local path or URI. path = try_path(ui, source) if path is not None: -url = path.rawloc +urls.append(path.rawloc) else: -url = source -return parseurl(url, default_branches) +urls.append(source) +if len(urls) != 1: +if source is None: +msg = _("default path point to %d urls while %s only support one") +msg %= (len(urls), action) +else: +msg = _("path point to %d urls while %s only support one: %s") +msg %= (len(urls), action, source) +raise error.Abort(msg) +return parseurl(urls[0], default_branches) def get_clone_path(ui, source, default_branches=()): """return the `(origsource, path, branch)` selected as clone source""" +urls = [] if source is None: if b'default' in ui.paths: -url = ui.paths[b'default'].rawloc +urls.extend(p.rawlo
D10446: urlutil: extract `chain_path` in a function
marmoute created this revision. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REVISION SUMMARY This will no longer modify `path` inplace so it does not make much sense as a method. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10446 AFFECTED FILES mercurial/utils/urlutil.py CHANGE DETAILS diff --git a/mercurial/utils/urlutil.py b/mercurial/utils/urlutil.py --- a/mercurial/utils/urlutil.py +++ b/mercurial/utils/urlutil.py @@ -611,7 +611,7 @@ self[name] = path(ui, name, rawloc=loc, suboptions=sub_opts) for name, p in sorted(self.items()): -p.chain_path(ui, self) +self[name] = _chain_path(p, ui, self) def getpath(self, ui, name, default=None): """Return a ``path`` from a string, falling back to default. @@ -704,6 +704,33 @@ return value +def _chain_path(path, ui, paths): +"""return the result of "path://" logic applied on a given path""" +if path.url.scheme == b'path': +assert path.url.path is None +subpath = paths.get(path.url.host) +if subpath is None: +m = _(b'cannot use `%s`, "%s" is not a known path') +m %= (path.rawloc, path.url.host) +raise error.Abort(m) +if subpath.raw_url.scheme == b'path': +m = _(b'cannot use `%s`, "%s" is also defined as a `path://`') +m %= (path.rawloc, path.url.host) +raise error.Abort(m) +path.url = subpath.url +path.rawloc = subpath.rawloc +path.loc = subpath.loc +if path.branch is None: +path.branch = subpath.branch +else: +base = path.rawloc.rsplit(b'#', 1)[0] +path.rawloc = b'%s#%s' % (base, path.branch) +suboptions = subpath._all_sub_opts.copy() +suboptions.update(path._own_sub_opts) +path._apply_suboptions(ui, suboptions) +return path + + class path(object): """Represents an individual path and its configuration.""" @@ -756,31 +783,6 @@ self._apply_suboptions(ui, sub_opts) -def chain_path(self, ui, paths): -if self.url.scheme == b'path': -assert self.url.path is None -try: -subpath = paths[self.url.host] -except KeyError: -m = _(b'cannot use `%s`, "%s" is not a known path') -m %= (self.rawloc, self.url.host) -raise error.Abort(m) -if subpath.raw_url.scheme == b'path': -m = _(b'cannot use `%s`, "%s" is also defined as a `path://`') -m %= (self.rawloc, self.url.host) -raise error.Abort(m) -self.url = subpath.url -self.rawloc = subpath.rawloc -self.loc = subpath.loc -if self.branch is None: -self.branch = subpath.branch -else: -base = self.rawloc.rsplit(b'#', 1)[0] -self.rawloc = b'%s#%s' % (base, self.branch) -suboptions = subpath._all_sub_opts.copy() -suboptions.update(self._own_sub_opts) -self._apply_suboptions(ui, suboptions) - def copy(self): """make a copy of this path object""" new = self.__class__() To: marmoute, #hg-reviewers Cc: mercurial-patches, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D10444: template: add a `paths` field to all entry in peersurl
marmoute created this revision. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REVISION SUMMARY This make it possible to display multiple path per name in the near future. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10444 AFFECTED FILES mercurial/templatekw.py tests/test-paths.t CHANGE DETAILS diff --git a/tests/test-paths.t b/tests/test-paths.t --- a/tests/test-paths.t +++ b/tests/test-paths.t @@ -98,6 +98,9 @@ expand: $TESTTMP/a/$SOMETHING/bar $ hg log -rnull -T '{get(peerurls, "dupe")}\n' $TESTTMP/b#tip + $ hg log -rnull -T '{peerurls % "{urls|json}\n"}' + [{"pushurl": "https://example.com/dupe";, "url": "$TESTTMP/b#tip"}] + [{"url": "$TESTTMP/a/$SOMETHING/bar"}] (sub options can be populated by map/dot operation) diff --git a/mercurial/templatekw.py b/mercurial/templatekw.py --- a/mercurial/templatekw.py +++ b/mercurial/templatekw.py @@ -670,7 +670,12 @@ def makemap(k): p = paths[k] d = {b'name': k, b'url': p.rawloc} -d.update((o, v) for o, v in sorted(pycompat.iteritems(p.suboptions))) +sub_opts = util.sortdict(sorted(pycompat.iteritems(p.suboptions))) +d.update(sub_opts) +path_dict = util.sortdict() +path_dict[b'url'] = p.rawloc +path_dict.update(sub_opts) +d[b'urls'] = [path_dict] return d def format_one(k): To: marmoute, #hg-reviewers Cc: mercurial-patches, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D10445: urlutil: add a `copy` method to `path
marmoute created this revision. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REVISION SUMMARY This will be useful when inheriting from multiple path at the same time. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10445 AFFECTED FILES mercurial/utils/urlutil.py CHANGE DETAILS diff --git a/mercurial/utils/urlutil.py b/mercurial/utils/urlutil.py --- a/mercurial/utils/urlutil.py +++ b/mercurial/utils/urlutil.py @@ -707,7 +707,7 @@ class path(object): """Represents an individual path and its configuration.""" -def __init__(self, ui, name, rawloc=None, suboptions=None): +def __init__(self, ui=None, name=None, rawloc=None, suboptions=None): """Construct a path from its config options. ``ui`` is the ``ui`` instance the path is coming from. @@ -719,6 +719,13 @@ filesystem path with a .hg directory or b) a URL. If not, ``ValueError`` is raised. """ +if ui is None: +# used in copy +assert name is None +assert rawloc is None +assert suboptions is None +return + if not rawloc: raise ValueError(b'rawloc must be defined') @@ -774,6 +781,16 @@ suboptions.update(self._own_sub_opts) self._apply_suboptions(ui, suboptions) +def copy(self): +"""make a copy of this path object""" +new = self.__class__() +for k, v in self.__dict__.items(): +new_copy = getattr(v, 'copy', None) +if new_copy is not None: +v = new_copy() +new.__dict__[k] = v +return new + def _validate_path(self): # When given a raw location but not a symbolic name, validate the # location is valid. To: marmoute, #hg-reviewers Cc: mercurial-patches, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D10442: template: use `list_paths` in `peerurls`
marmoute created this revision. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REVISION SUMMARY Using common code will make it simpler to update the logic behind the path definition and storage. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10442 AFFECTED FILES mercurial/templatekw.py CHANGE DETAILS diff --git a/mercurial/templatekw.py b/mercurial/templatekw.py --- a/mercurial/templatekw.py +++ b/mercurial/templatekw.py @@ -29,7 +29,10 @@ templateutil, util, ) -from .utils import stringutil +from .utils import ( +stringutil, +urlutil, +) _hybrid = templateutil.hybrid hybriddict = templateutil.hybriddict @@ -661,9 +664,8 @@ repo = context.resource(mapping, b'repo') # see commands.paths() for naming of dictionary keys paths = repo.ui.paths -urls = util.sortdict( -(k, p.rawloc) for k, p in sorted(pycompat.iteritems(paths)) -) +all_paths = urlutil.list_paths(repo.ui) +urls = util.sortdict((k, p.rawloc) for k, p in all_paths) def makemap(k): p = paths[k] To: marmoute, #hg-reviewers Cc: mercurial-patches, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D10443: template: make an explicit closure for formatting entry in peerurls
marmoute created this revision. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REVISION SUMMARY This is about to be become significantly more complicated as `ui.path[x]` will become a list. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10443 AFFECTED FILES mercurial/templatekw.py CHANGE DETAILS diff --git a/mercurial/templatekw.py b/mercurial/templatekw.py --- a/mercurial/templatekw.py +++ b/mercurial/templatekw.py @@ -673,7 +673,10 @@ d.update((o, v) for o, v in sorted(pycompat.iteritems(p.suboptions))) return d -return _hybrid(None, urls, makemap, lambda k: b'%s=%s' % (k, urls[k])) +def format_one(k): +return b'%s=%s' % (k, urls[k]) + +return _hybrid(None, urls, makemap, format_one) @templatekeyword(b"predecessors", requires={b'repo', b'ctx'}) To: marmoute, #hg-reviewers Cc: mercurial-patches, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D10440: urlutil: introduce a new `list_paths` function
marmoute created this revision. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REVISION SUMMARY This function will be useful for command and template that wants to display path related information. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10440 AFFECTED FILES mercurial/utils/urlutil.py CHANGE DETAILS diff --git a/mercurial/utils/urlutil.py b/mercurial/utils/urlutil.py --- a/mercurial/utils/urlutil.py +++ b/mercurial/utils/urlutil.py @@ -445,6 +445,18 @@ return bytes(u) +def list_paths(ui, target_path=None): +"""list all the (name, paths) in the passed ui""" +if target_path is None: +return sorted(pycompat.iteritems(ui.paths)) +else: +path = ui.paths.get(target_path) +if path is None: +return [] +else: +return [(target_path, path)] + + def try_path(ui, url): """try to build a path from a url To: marmoute, #hg-reviewers Cc: mercurial-patches, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D10441: paths: use `list_paths` in `hg paths`
marmoute created this revision. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REVISION SUMMARY Using common code will make it simpler to update the logic behind the path definition and storage. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10441 AFFECTED FILES mercurial/commands.py CHANGE DETAILS diff --git a/mercurial/commands.py b/mercurial/commands.py --- a/mercurial/commands.py +++ b/mercurial/commands.py @@ -5128,15 +5128,9 @@ """ opts = pycompat.byteskwargs(opts) + +pathitems = urlutil.list_paths(ui, search) ui.pager(b'paths') -if search: -pathitems = [ -(name, path) -for name, path in pycompat.iteritems(ui.paths) -if name == search -] -else: -pathitems = sorted(pycompat.iteritems(ui.paths)) fm = ui.formatter(b'paths', opts) if fm.isplain(): To: marmoute, #hg-reviewers Cc: mercurial-patches, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Failed pipeline for branch/default | mercurial-devel | 29d82ba3
Pipeline #20649 has failed! Project: mercurial-devel ( https://foss.heptapod.net/octobus/mercurial-devel ) Branch: branch/default ( https://foss.heptapod.net/octobus/mercurial-devel/-/commits/branch/default ) Commit: 29d82ba3 ( https://foss.heptapod.net/octobus/mercurial-devel/-/commit/29d82ba35fde9fb5b28bfec2408ea3fb18291d62 ) Commit Message: fetch: use `get_unique_pull_path` to retrieve t... Commit Author: Pierre-Yves David ( https://foss.heptapod.net/marmoute ) Pipeline #20649 ( https://foss.heptapod.net/octobus/mercurial-devel/-/pipelines/20649 ) triggered by Administrator ( https://foss.heptapod.net/root ) had 1 failed build. Job #185860 ( https://foss.heptapod.net/octobus/mercurial-devel/-/jobs/185860/raw ) Stage: tests Name: test-py2-rust -- You're receiving this email because of your account on foss.heptapod.net. ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
[Bug 6508] New: sparse extention can't avoid sub-repo
https://bz.mercurial-scm.org/show_bug.cgi?id=6508 Bug ID: 6508 Summary: sparse extention can't avoid sub-repo Product: Mercurial Version: 5.7.1 Hardware: PC OS: Windows Status: UNCONFIRMED Severity: bug Priority: wish Component: Mercurial Assignee: bugzi...@mercurial-scm.org Reporter: alexraynepe...@gmail.com CC: mercurial-devel@mercurial-scm.org Python Version: --- Hallow! use hg 5.7.1 py2 on win8.1 ru my repo have a big set of sub-repos, most of them - [git] i try checkout sparse of repo - a few directories, that not have any of sub-repos. but checkout sparse - upload all sub-repos. it's awful. -- You are receiving this mail because: You are on the CC list for the bug. ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D10439: urlutil: deprecate `getpath`
marmoute created this revision. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REVISION SUMMARY There as no remaining user of that function. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10439 AFFECTED FILES mercurial/ui.py mercurial/utils/urlutil.py CHANGE DETAILS diff --git a/mercurial/utils/urlutil.py b/mercurial/utils/urlutil.py --- a/mercurial/utils/urlutil.py +++ b/mercurial/utils/urlutil.py @@ -610,6 +610,8 @@ Returns None if ``name`` is not a registered path, a URI, or a local path to a repo. """ +msg = b'getpath is deprecated, use `get_*` functions from urlutil' +self.deprecwarn(msg, '6.0') # Only fall back to default if no path was requested. if name is None: if not default: diff --git a/mercurial/ui.py b/mercurial/ui.py --- a/mercurial/ui.py +++ b/mercurial/ui.py @@ -1058,6 +1058,8 @@ This method exist as `getpath` need a ui for potential warning message. """ +msg = b'ui.getpath is deprecated, use `get_*` functions from urlutil' +self.deprecwarn(msg, '6.0') return self.paths.getpath(self, *args, **kwargs) @property To: marmoute, #hg-reviewers Cc: mercurial-patches, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D10436: perfphasesremote: use `get_unique_push_path` if available
marmoute created this revision. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REVISION SUMMARY After `ui.expandpath` we are not after `getpath` (that will be much simpler). The reason is still the fact we can't rely on getting a single url from a single path anymore. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10436 AFFECTED FILES contrib/perf.py CHANGE DETAILS diff --git a/contrib/perf.py b/contrib/perf.py --- a/contrib/perf.py +++ b/contrib/perf.py @@ -1414,7 +1414,13 @@ opts = _byteskwargs(opts) timer, fm = gettimer(ui, opts) -path = ui.getpath(dest, default=(b'default-push', b'default')) +try: +from mercurial.utils.urlutil import get_unique_push_path + +path = get_unique_push_path(repo, ui, dest) +except ImportError: +path = ui.getpath(dest, default=(b'default-push', b'default')) + if not path: raise error.Abort( b'default repository not configured!', To: marmoute, #hg-reviewers Cc: mercurial-patches, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D10435: revset: drop an outdated comment
marmoute created this revision. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REVISION SUMMARY There is not `ui.expandpath` call there anymore. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10435 AFFECTED FILES mercurial/revset.py CHANGE DETAILS diff --git a/mercurial/revset.py b/mercurial/revset.py --- a/mercurial/revset.py +++ b/mercurial/revset.py @@ -1856,7 +1856,6 @@ l and getstring(l[0], _(b"outgoing requires a repository path")) or b'' ) if dest: -# ui.getpath() explicitly tests for None, not just a boolean dests = [dest] else: dests = [] To: marmoute, #hg-reviewers Cc: mercurial-patches, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D10438: urlutil: inline the relevant part of `getpath` in `get_push_paths`
marmoute created this revision. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REVISION SUMMARY The part that `get_push_paths` needs is quite simple, inclining will help us to deprecated `getpath`. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10438 AFFECTED FILES mercurial/utils/urlutil.py CHANGE DETAILS diff --git a/mercurial/utils/urlutil.py b/mercurial/utils/urlutil.py --- a/mercurial/utils/urlutil.py +++ b/mercurial/utils/urlutil.py @@ -471,7 +471,15 @@ ) else: for dest in dests: -yield ui.getpath(dest) +if dest in ui.paths: +yield ui.paths[dest] +else: +path = try_path(ui, dest) +if path is None: +msg = _(b'repository %s does not exist') +msg %= dest +raise error.RepoError(msg) +yield path def get_pull_paths(repo, ui, sources, default_branches=()): To: marmoute, #hg-reviewers Cc: mercurial-patches, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D10437: url_util: introduce a `try_path` function
marmoute created this revision. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REVISION SUMMARY That function… try a build a path, returning None on failure. This helps us to simplify various part of the existing code. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10437 AFFECTED FILES mercurial/utils/urlutil.py CHANGE DETAILS diff --git a/mercurial/utils/urlutil.py b/mercurial/utils/urlutil.py --- a/mercurial/utils/urlutil.py +++ b/mercurial/utils/urlutil.py @@ -445,6 +445,18 @@ return bytes(u) +def try_path(ui, url): +"""try to build a path from a url + +Return None if no Path could built. +""" +try: +# we pass the ui instance are warning might need to be issued +return path(ui, None, rawloc=url) +except ValueError: +return None + + def get_push_paths(repo, ui, dests): """yields all the `path` selected as push destination by `dests`""" if not dests: @@ -471,10 +483,10 @@ url = ui.paths[source].rawloc else: # Try to resolve as a local path or URI. -try: -# we pass the ui instance are warning might need to be issued -url = path(ui, None, rawloc=source).rawloc -except ValueError: +path = try_path(ui, source) +if path is not None: +url = path.rawloc +else: url = source yield parseurl(url, default_branches) @@ -520,10 +532,10 @@ url = ui.paths[source].rawloc else: # Try to resolve as a local path or URI. -try: -# we pass the ui instance are warning might need to be issued -url = path(ui, None, rawloc=source).rawloc -except ValueError: +path = try_path(ui, source) +if path is not None: +url = path.rawloc +else: url = source return parseurl(url, default_branches) @@ -542,10 +554,10 @@ url = ui.paths[source].rawloc else: # Try to resolve as a local path or URI. -try: -# we pass the ui instance are warning might need to be issued -url = path(ui, None, rawloc=source).rawloc -except ValueError: +path = try_path(ui, source) +if path is not None: +url = path.rawloc +else: url = source clone_path, branch = parseurl(url, default_branches) return url, clone_path, branch @@ -607,16 +619,14 @@ # This may need to raise in the future. if not name: return None - -try: +if name in self: return self[name] -except KeyError: +else: # Try to resolve as a local path or URI. -try: -# we pass the ui instance are warning might need to be issued -return path(ui, None, rawloc=name) -except ValueError: +path = try_path(ui, name) +if path is None: raise error.RepoError(_(b'repository %s does not exist') % name) +return path.rawloc _pathsuboptions = {} To: marmoute, #hg-reviewers Cc: mercurial-patches, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
Failed pipeline for branch/default | mercurial-devel | c9fba0ab
Pipeline #20627 has failed! Project: mercurial-devel ( https://foss.heptapod.net/octobus/mercurial-devel ) Branch: branch/default ( https://foss.heptapod.net/octobus/mercurial-devel/-/commits/branch/default ) Commit: c9fba0ab ( https://foss.heptapod.net/octobus/mercurial-devel/-/commit/c9fba0ab1bb15f53c6521041318cf9b1635296b7 ) Commit Message: split: avoid strip if split is a no-op (identic... Commit Author: Kyle Lippincott ( https://foss.heptapod.net/spectral ) Pipeline #20627 ( https://foss.heptapod.net/octobus/mercurial-devel/-/pipelines/20627 ) triggered by Pierre-Yves David ( https://foss.heptapod.net/marmoute ) had 2 failed builds. Job #185686 ( https://foss.heptapod.net/octobus/mercurial-devel/-/jobs/185686/raw ) Stage: tests Name: test-py3-rhg Job #185688 ( https://foss.heptapod.net/octobus/mercurial-devel/-/jobs/185688/raw ) Stage: tests Name: test-py3-chg -- You're receiving this email because of your account on foss.heptapod.net. ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
D10434: subrepo: introduce a `repo_rel_or_abs_source` function
marmoute created this revision. Herald added a reviewer: hg-reviewers. Herald added a subscriber: mercurial-patches. REVISION SUMMARY The `subrepoutil` module has various function to compute the path of a sub-repository compared to the root of the top repository. However, they was no function available to compute the relative path of the repository "source". And we need this information for exchange operation (in our case, `hg outgoing`). The information is currently build using the `repo._subtoppath` hack. We reuse the same logic but in a dedicated function independent of the `repo._subtoppath` hack. REPOSITORY rHG Mercurial BRANCH default REVISION DETAIL https://phab.mercurial-scm.org/D10434 AFFECTED FILES mercurial/subrepoutil.py CHANGE DETAILS diff --git a/mercurial/subrepoutil.py b/mercurial/subrepoutil.py --- a/mercurial/subrepoutil.py +++ b/mercurial/subrepoutil.py @@ -383,6 +383,24 @@ return subs, commitsubs, newstate +def repo_rel_or_abs_source(repo): +"""return the source of this repo + +Either absolute or relative the outermost repo""" +parent = repo +chunks = [] +while util.safehasattr(parent, b'_subparent'): +source = urlutil.url(parent._subsource) +chunks.append(bytes(source)) +if source.isabs(): +break +parent = parent._subparent + +chunks.reverse() +path = posixpath.join(*chunks) +return posixpath.normpath(path) + + def reporelpath(repo): # type: (localrepo.localrepository) -> bytes """return path to this (sub)repo as seen from outermost repo""" To: marmoute, #hg-reviewers Cc: mercurial-patches, mercurial-devel ___ Mercurial-devel mailing list Mercurial-devel@mercurial-scm.org https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel