mirror of
https://github.com/Stone-Red-Code/dvc.git
synced 2026-11-02 07:18:25 +01:00
fix remote config completion
This commit is contained in:
+61
-6
@@ -31,6 +31,27 @@ _dvc_compgen_remotes() {
|
|||||||
_dvc_compgen_config_vars() {
|
_dvc_compgen_config_vars() {
|
||||||
compgen -W "${_dvc_config_vars[*]}" -- $1
|
compgen -W "${_dvc_config_vars[*]}" -- $1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_dvc_compgen_remote_config_vars() {
|
||||||
|
local cur prev words cword remote_name filtered
|
||||||
|
_init_completion || return
|
||||||
|
|
||||||
|
# last non-option word before cursor
|
||||||
|
local nonopts=()
|
||||||
|
for w in "${words[@]:1:$((cword-1))}"; do
|
||||||
|
[[ $w == -* ]] || nonopts+=("$w")
|
||||||
|
done
|
||||||
|
|
||||||
|
remote_name="${nonopts[-1]}"
|
||||||
|
if [[ -n $remote_name ]]; then
|
||||||
|
local _dvc_remote_config_vars=($(
|
||||||
|
dvc config --available-options -q 2> /dev/null \
|
||||||
|
| grep "^remote\\.${remote_name}\\." \
|
||||||
|
| sed "s/^remote\\.${remote_name}\\.//"
|
||||||
|
))
|
||||||
|
compgen -W "${_dvc_remote_config_vars[*]}" -- $1
|
||||||
|
fi
|
||||||
|
}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
ZSH_PREAMBLE = """
|
ZSH_PREAMBLE = """
|
||||||
@@ -69,9 +90,27 @@ _dvc_compadd_remotes() {
|
|||||||
_describe 'remotes' "($(dvc remote list | cut -d' ' -f1))"
|
_describe 'remotes' "($(dvc remote list | cut -d' ' -f1))"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_dvc_config_config_vars_for_completion() {
|
||||||
|
dvc config --available-options -q 2> /dev/null
|
||||||
|
}
|
||||||
|
|
||||||
_dvc_compadd_config_vars() {
|
_dvc_compadd_config_vars() {
|
||||||
_describe 'config_vars' _dvc_config_vars
|
_describe 'config_vars' _dvc_config_vars
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_dvc_compadd_remote_config_vars() {
|
||||||
|
local remote_name filtered
|
||||||
|
|
||||||
|
# last non-option word before cursor
|
||||||
|
remote_name=${${words[1,CURRENT-1]##-*}[-1]}
|
||||||
|
if [[ -n $remote_name ]]; then
|
||||||
|
filtered=$(_dvc_config_config_vars_for_completion \\
|
||||||
|
| grep "^remote.${remote_name}\\\\." \\
|
||||||
|
| sed "s/^remote\\\\.${remote_name}\\\\.//"
|
||||||
|
)
|
||||||
|
compadd -- $=filtered
|
||||||
|
fi
|
||||||
|
}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
FISH_PREAMBLE = """
|
FISH_PREAMBLE = """
|
||||||
@@ -100,6 +139,17 @@ end
|
|||||||
function __fish_complete_dvc_remotes
|
function __fish_complete_dvc_remotes
|
||||||
dvc remote list | cut -d' ' -f1
|
dvc remote list | cut -d' ' -f1
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function __fish_complete_dvc_remote_config_vars
|
||||||
|
# last non-option word before cursor
|
||||||
|
set -l remote_name (commandline -opc | string match -rv '^-' | tail -n 1)
|
||||||
|
|
||||||
|
if test -n "$remote_name"
|
||||||
|
dvc config --available-options -q 2>/dev/null |
|
||||||
|
string match -re "^remote\\.$remote_name\\." |
|
||||||
|
string replace -r "^remote\\.$remote_name\\." ''
|
||||||
|
end
|
||||||
|
end
|
||||||
"""
|
"""
|
||||||
|
|
||||||
PREAMBLE = {
|
PREAMBLE = {
|
||||||
@@ -113,32 +163,37 @@ DIR = shtab.DIRECTORY
|
|||||||
DVC_FILE = {
|
DVC_FILE = {
|
||||||
"bash": "_dvc_compgen_DVCFiles",
|
"bash": "_dvc_compgen_DVCFiles",
|
||||||
"zsh": "_dvc_compadd_DVCFiles",
|
"zsh": "_dvc_compadd_DVCFiles",
|
||||||
"fish": "__fish_complete_dvc_files",
|
"fish": '-f -a "(__fish_complete_dvc_files)"',
|
||||||
}
|
}
|
||||||
STAGE = {
|
STAGE = {
|
||||||
"bash": "_dvc_compgen_stages",
|
"bash": "_dvc_compgen_stages",
|
||||||
"zsh": "_dvc_compadd_stages",
|
"zsh": "_dvc_compadd_stages",
|
||||||
"fish": "__fish_complete_dvc_stages",
|
"fish": '-f -a "(__fish_complete_dvc_stages)"',
|
||||||
}
|
}
|
||||||
DVCFILES_AND_STAGE = {
|
DVCFILES_AND_STAGE = {
|
||||||
"bash": "_dvc_compgen_stages_and_files",
|
"bash": "_dvc_compgen_stages_and_files",
|
||||||
"zsh": "_dvc_compadd_stages_and_files",
|
"zsh": "_dvc_compadd_stages_and_files",
|
||||||
"fish": "__fish_complete_dvc_stages_and_files",
|
"fish": '-f -a "(__fish_complete_dvc_stages_and_files)"',
|
||||||
}
|
}
|
||||||
EXPERIMENT = {
|
EXPERIMENT = {
|
||||||
"bash": "_dvc_compgen_exps",
|
"bash": "_dvc_compgen_exps",
|
||||||
"zsh": "_dvc_compadd_exps",
|
"zsh": "_dvc_compadd_exps",
|
||||||
"fish": "__fish_complete_dvc_experiments",
|
"fish": '-f -a "(__fish_complete_dvc_experiments)"',
|
||||||
}
|
}
|
||||||
REMOTE = {
|
REMOTE = {
|
||||||
"bash": "_dvc_compgen_remotes",
|
"bash": "_dvc_compgen_remotes",
|
||||||
"zsh": "_dvc_compadd_remotes",
|
"zsh": "_dvc_compadd_remotes",
|
||||||
"fish": "__fish_complete_dvc_remotes",
|
"fish": '-f -a "(__fish_complete_dvc_remotes)"',
|
||||||
}
|
}
|
||||||
CONFIG_VARS = {
|
CONFIG_VARS = {
|
||||||
"bash": "_dvc_compgen_config_vars",
|
"bash": "_dvc_compgen_config_vars",
|
||||||
"zsh": "_dvc_compadd_config_vars",
|
"zsh": "_dvc_compadd_config_vars",
|
||||||
"fish": "__fish_complete_dvc_config_vars",
|
"fish": '-f -a "(__fish_complete_dvc_config_vars)"',
|
||||||
|
}
|
||||||
|
REMOTE_CONFIG_VARS = {
|
||||||
|
"bash": "_dvc_compgen_remote_config_vars",
|
||||||
|
"zsh": "_dvc_compadd_remote_config_vars",
|
||||||
|
"fish": '-f -a "(__fish_complete_dvc_remote_config_vars)"',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -40,6 +40,15 @@ class CmdConfig(CmdBaseNoRepo):
|
|||||||
self.config = Config.from_cwd(validate=False)
|
self.config = Config.from_cwd(validate=False)
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
|
if self.args.available_options:
|
||||||
|
from dvc.config_schema import contextual_config_vars_for_completion
|
||||||
|
|
||||||
|
ui.write(
|
||||||
|
"\n".join(list(contextual_config_vars_for_completion(self.config))),
|
||||||
|
force=True,
|
||||||
|
)
|
||||||
|
return 0
|
||||||
|
|
||||||
if self.args.show_origin and (self.args.value or self.args.unset):
|
if self.args.show_origin and (self.args.value or self.args.unset):
|
||||||
logger.error(
|
logger.error(
|
||||||
"--show-origin can't be used together with any of these "
|
"--show-origin can't be used together with any of these "
|
||||||
@@ -212,6 +221,9 @@ def add_parser(subparsers, parent_parser):
|
|||||||
help=CONFIG_HELP,
|
help=CONFIG_HELP,
|
||||||
formatter_class=formatter.RawDescriptionHelpFormatter,
|
formatter_class=formatter.RawDescriptionHelpFormatter,
|
||||||
)
|
)
|
||||||
|
config_parser.add_argument(
|
||||||
|
"--available-options", default=False, action="store_true"
|
||||||
|
)
|
||||||
config_parser.add_argument(
|
config_parser.add_argument(
|
||||||
"-u",
|
"-u",
|
||||||
"--unset",
|
"--unset",
|
||||||
|
|||||||
@@ -233,7 +233,9 @@ def add_parser(subparsers, parent_parser):
|
|||||||
remote_modify_parser.add_argument(
|
remote_modify_parser.add_argument(
|
||||||
"name", help="Name of the remote"
|
"name", help="Name of the remote"
|
||||||
).complete = completion.REMOTE
|
).complete = completion.REMOTE
|
||||||
remote_modify_parser.add_argument("option", help="Name of the option to modify.")
|
remote_modify_parser.add_argument(
|
||||||
|
"option", help="Name of the option to modify."
|
||||||
|
).complete = completion.REMOTE_CONFIG_VARS
|
||||||
remote_modify_parser.add_argument(
|
remote_modify_parser.add_argument(
|
||||||
"value", nargs="?", help="(optional) Value of the option."
|
"value", nargs="?", help="(optional) Value of the option."
|
||||||
)
|
)
|
||||||
|
|||||||
+33
-14
@@ -60,23 +60,27 @@ def Choices(*choices): # noqa: N802
|
|||||||
return Any(*choices, msg="expected one of {}".format(", ".join(choices)))
|
return Any(*choices, msg="expected one of {}".format(", ".join(choices)))
|
||||||
|
|
||||||
|
|
||||||
|
def _get_schema_from_url(url: str) -> str:
|
||||||
|
parsed = urlparse(url)
|
||||||
|
# Windows absolute paths should really have scheme == "" (local)
|
||||||
|
if os.name == "nt" and len(parsed.scheme) == 1 and not parsed.netloc:
|
||||||
|
return ""
|
||||||
|
if not parsed.netloc:
|
||||||
|
return ""
|
||||||
|
return parsed.scheme
|
||||||
|
|
||||||
|
|
||||||
def ByUrl(mapping): # noqa: N802
|
def ByUrl(mapping): # noqa: N802
|
||||||
schemas = walk_values(Schema, mapping)
|
schemas: dict[str, Schema] = walk_values(Schema, mapping)
|
||||||
|
|
||||||
def validate(data):
|
def validate(data):
|
||||||
if "url" not in data:
|
if "url" not in data:
|
||||||
raise Invalid("expected 'url'")
|
raise Invalid("expected 'url'")
|
||||||
|
|
||||||
parsed = urlparse(data["url"])
|
scheme = _get_schema_from_url(data["url"])
|
||||||
# Windows absolute paths should really have scheme == "" (local)
|
if scheme not in schemas:
|
||||||
if os.name == "nt" and len(parsed.scheme) == 1 and not parsed.netloc:
|
raise Invalid(f"Unsupported URL type {scheme}://")
|
||||||
return schemas[""](data)
|
return schemas[scheme](data)
|
||||||
if not parsed.netloc:
|
|
||||||
return schemas[""](data)
|
|
||||||
if parsed.scheme not in schemas:
|
|
||||||
raise Invalid(f"Unsupported URL type {parsed.scheme}://")
|
|
||||||
|
|
||||||
return schemas[parsed.scheme](data)
|
|
||||||
|
|
||||||
return validate
|
return validate
|
||||||
|
|
||||||
@@ -396,9 +400,24 @@ def config_vars_for_completion(d: dict = SCHEMA, path: str = "") -> "Iterator[st
|
|||||||
k = k.schema
|
k = k.schema
|
||||||
if not isinstance(k, str):
|
if not isinstance(k, str):
|
||||||
continue
|
continue
|
||||||
|
keypath = f"{path}.{k}" if path else k
|
||||||
keypath = path + k
|
|
||||||
if isinstance(v, dict):
|
if isinstance(v, dict):
|
||||||
yield from config_vars_for_completion(v, keypath + ".")
|
yield from config_vars_for_completion(v, keypath)
|
||||||
else:
|
else:
|
||||||
yield keypath
|
yield keypath
|
||||||
|
|
||||||
|
|
||||||
|
def contextual_config_vars_for_completion(config) -> "Iterator[str]":
|
||||||
|
yield from config_vars_for_completion()
|
||||||
|
for name, data in config["remote"].items():
|
||||||
|
if "url" not in data:
|
||||||
|
continue
|
||||||
|
scheme = _get_schema_from_url(data["url"])
|
||||||
|
if scheme not in REMOTE_SCHEMAS:
|
||||||
|
continue
|
||||||
|
schema = REMOTE_SCHEMAS[scheme]
|
||||||
|
if schema:
|
||||||
|
yield from config_vars_for_completion(schema, f"remote.{name}") # type: ignore[arg-type]
|
||||||
|
|
||||||
|
for name in config["db"]:
|
||||||
|
yield from config_vars_for_completion(SCHEMA["db"], f"db.{name}") # type: ignore[arg-type]
|
||||||
|
|||||||
Reference in New Issue
Block a user