From cf91fe29864a38f71d67d4e6b0c9e85922439c85 Mon Sep 17 00:00:00 2001 From: Edwin Kofler Date: Wed, 27 Sep 2023 14:55:28 -0700 Subject: [PATCH 1/3] feat(checkstyle): Add fixers and misuse detection of `display_{info,error}()` --- scripts/checkstyle.py | 170 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 159 insertions(+), 11 deletions(-) diff --git a/scripts/checkstyle.py b/scripts/checkstyle.py index 28294ea0b..9e5713b39 100755 --- a/scripts/checkstyle.py +++ b/scripts/checkstyle.py @@ -35,7 +35,7 @@ class c: UNDERLINE = '\033[4m' LINK: Callable[[str, str], str] = lambda href, text: f'\033]8;;{href}\a{text}\033]8;;\a' -def utilGetStrs(line: Any, m: Any): +def utilGetStrs(line: str, m: Any): return ( line[0:m.start('match')], line[m.start('match'):m.end('match')], @@ -90,6 +90,42 @@ def noVerboseRedirectionFixer(line: str, m: Any) -> str: return f'{prestr}&>/dev/null{poststr}' +def noExplicitStandardOutputRedirectionFixer(line: str, m: Any) -> str: + prestr, _, poststr = utilGetStrs(line, m) + + return f'{prestr}>&2{poststr}' + +# Before: printf '%s\n' 'text' >&2 +# After: display_error 'text' +def noPrintfStandardErrorFixer(line: str, m: Any) -> str: + prestr, _, poststr = utilGetStrs(line, m) + + poststr = poststr.rstrip() + if poststr.endswith('>&2'): # str.removesuffix Python 3.9 + poststr = poststr[0:len(poststr)-len('>&2')] + poststr = poststr.rstrip() + + return f'{prestr}display_error{poststr}' + +# Before: display_info 'text\n' +# After: display_info 'text' +def noDisplayFnNewlineFixer(line: str, m: Any) -> str: + prestr, midstr, poststr = utilGetStrs(line, m) + + midstr = midstr.removesuffix('\\n') + + return f'{prestr}{midstr}{poststr}' + +# Before: display_info '%s\n' 'text' +# After: display_info 'text' +def noDisplayFnFormattingArgFixer(line: str, m: Any) -> str: + prestr, _, poststr = utilGetStrs(line, m) + + prestr = prestr.rstrip() + poststr = poststr.lstrip() + + return f'{prestr} {poststr}' + def lintfile(file: Path, rules: List[Rule], options: Dict[str, Any]): content_arr = file.read_text().split('\n') @@ -106,6 +142,13 @@ def lintfile(file: Path, rules: List[Rule], options: Dict[str, Any]): if file.name.endswith('.bash') or file.name.endswith('.bats'): should_run = True + if 'matchesIgnored' in rule: + for glb in rule['matchesIgnored']: + if file.match(glb): + should_run = False + break + + if options['verbose']: print(f'{str(file)}: {should_run}') @@ -142,11 +185,15 @@ def main(): 'fixerFn': noDoubleBackslashFixer, 'testPositiveMatches': [ 'printf "%s\\\\n" "Hai"', - 'echo -n "Hello\\\\n"' + 'echo -n "Hello\\\\n"', + ], + 'testPositiveMatchesFixed': [ + 'printf "%s\\n" "Hai"', + 'echo -n "Hello\\n"', ], 'testNegativeMatches': [ 'printf "%s\\n" "Hai"', - 'echo -n "Hello\\n"' + 'echo -n "Hello\\n"', ], }, { @@ -156,10 +203,13 @@ def main(): 'fileTypes': ['bash', 'sh'], 'fixerFn': noPwdCaptureFixer, 'testPositiveMatches': [ - '$(pwd)' + '$(pwd)', + ], + 'testPositiveMatchesFixed': [ + '$PWD', ], 'testNegativeMatches': [ - '$PWD' + '$PWD', ], }, { @@ -172,6 +222,10 @@ def main(): '[ a == b ]', '[ "${lines[0]}" == blah ]', ], + 'testPositiveMatchesFixed': [ + '[ a = b ]', + '[ "${lines[0]}" = blah ]', + ], 'testNegativeMatches': [ '[ a = b ]', '[[ a = b ]]', @@ -189,8 +243,12 @@ def main(): 'fileTypes': ['bash', 'sh'], 'fixerFn': noFunctionKeywordFixer, 'testPositiveMatches': [ - 'function fn() { :; }', - 'function fn { :; }', + 'function fn1() { :; }', + 'function fn2 { :; }', + ], + 'testPositiveMatchesFixed': [ + 'fn1() { :; }', + 'fn2() { :; }', ], 'testNegativeMatches': [ 'fn() { :; }', @@ -203,14 +261,92 @@ def main(): 'fileTypes': ['bash'], 'fixerFn': noVerboseRedirectionFixer, 'testPositiveMatches': [ - 'echo woof >/dev/null 2>&1', - 'echo woof 2>/dev/null 1>&2', + 'echo woof1 >/dev/null 2>&1', + 'echo woof2 2>/dev/null 1>&2', + ], + 'testPositiveMatchesFixed': [ + 'echo woof1 &>/dev/null', + 'echo woof2 &>/dev/null', ], 'testNegativeMatches': [ 'echo woof &>/dev/null', 'echo woof >&/dev/null', ], }, + { + 'name': 'no-explicit-stdout-redirection', + 'regex': '(?P1>&2)', + 'reason': 'For consistency and to support less complex linters', + 'fileTypes': ['bash', 'sh'], + 'fixerFn': noExplicitStandardOutputRedirectionFixer, + 'testPositiveMatches': [ + 'echo blah 1>&2', + ], + 'testPositiveMatchesFixed': [ + 'echo blah >&2', + ], + 'testNegativeMatches': [ + 'echo blah >&2', + ], + }, + { + 'name': 'no-printf-standard-error', + 'regex': '(?Pdisplay_info|printf|echo).*(?P>&2)', + 'reason': 'Use `display_error`, which has shared semantics and logic', + 'fileTypes': ['bash', 'sh'], + 'matchesIgnored': ['scripts/*', 'asdf.sh'], + 'fixerFn': noPrintfStandardErrorFixer, + 'testPositiveMatches': [ + 'printf "text1" >&2', + "echo 'text2' >&2", + 'display_info text4 >&2', + ], + 'testPositiveMatchesFixed': [ + 'display_error "text1"', + "display_error 'text2'", + "display_error text4", + ], + 'testNegativeMatches': [ + 'echo woah1', + 'echo woah2', + '>&2 printf text3', + ], + }, + { + 'name': 'no-display-fn-newline', + 'regex': 'display_info[ \\t]+[\'"](?P.*?\\\\n)[\'"][ \\t]*$', + 'reason': 'Function `display_info` already prints a newline', + 'fileTypes': ['bash', 'sh'], + 'fixerFn': noDisplayFnNewlineFixer, + 'testPositiveMatches': [ + 'display_info "a\\n"', + "display_info 'b\\n'", + ], + 'testPositiveMatchesFixed': [ + 'display_info "a"', + "display_info 'b'", + ], + 'testNegativeMatches': [ + 'display_info c', + 'display_info "\\nd"' + ], + }, + { + 'name': 'no-display-formatting-arg', + 'regex': 'display_info[ \\t]+(?P[\'"]%s\\\\n[\'"])', + 'reason': 'Function `display_info` already prints a newline', + 'fileTypes': ['bash', 'sh'], + 'fixerFn': noDisplayFnFormattingArgFixer, + 'testPositiveMatches': [ + 'display_info "%s\\n" other', + ], + 'testPositiveMatchesFixed': [ + 'display_info other', + ], + 'testNegativeMatches': [ + 'display_info "%s\\n\\n"', + ], + }, ] [rule.update({ 'found': 0 }) for rule in rules] @@ -223,12 +359,24 @@ def main(): if args.internal_test_regex: for rule in rules: - for positiveMatch in rule['testPositiveMatches']: + for (i, positiveMatch) in enumerate(rule['testPositiveMatches']): m: Any = re.search(rule['regex'], positiveMatch) if m is None or m.group('match') is None: print(f'{c.MAGENTA}{rule["name"]}{c.RESET}: Failed {c.CYAN}positive{c.RESET} test:') print(f'=> {positiveMatch}') - print() + exit(1) + + if len(rule['testPositiveMatchesFixed']) < len(rule['testPositiveMatches']): + print(f'{c.MAGENTA}{rule["name"]}{c.RESET}: Failed {c.BLUE}fixer preliminary{c.RESET} test:') + print(f'=> Missing items in array: testPositiveMatchesFixed') + exit(1) + + fixedLine = rule['fixerFn'](positiveMatch, m) + if rule['testPositiveMatchesFixed'][i] != fixedLine: + print(f'{c.MAGENTA}{rule["name"]}{c.RESET}: Failed {c.BLUE}fixer{c.RESET} test:') + print(f'=> expected: {rule["testPositiveMatchesFixed"][i]}') + print(f'=> received: {fixedLine}') + exit(1) for negativeMatch in rule['testNegativeMatches']: m: Any = re.search(rule['regex'], negativeMatch) From 338a6cd454af7a4a657a26bdde80211ddc95852e Mon Sep 17 00:00:00 2001 From: Edwin Kofler Date: Wed, 27 Sep 2023 13:33:14 -0700 Subject: [PATCH 2/3] chore: Restructuring for readability --- lib/commands/command-current.bash | 2 +- .../command-export-shell-version.bash | 2 +- lib/functions/versions.bash | 2 +- lib/utils.bash | 24 +++++++++---------- scripts/install_dependencies.bash | 6 ++--- test/utils.bats | 4 ++-- 6 files changed, 20 insertions(+), 20 deletions(-) diff --git a/lib/commands/command-current.bash b/lib/commands/command-current.bash index f4724626e..3a7a21ebf 100644 --- a/lib/commands/command-current.bash +++ b/lib/commands/command-current.bash @@ -48,7 +48,7 @@ current_command() { local exit_status=0 local plugin - # printf "$terminal_format" "PLUGIN" "VERSION" "SET BY CONFIG" # disable this until we release headings across the board + # printf "$terminal_format" "PLUGIN" "VERSION" "SET BY CONFIG" # TODO: disable this until we release headings across the board if [ $# -eq 0 ]; then # shellcheck disable=SC2119 for plugin in $(plugin_list_command); do diff --git a/lib/commands/command-export-shell-version.bash b/lib/commands/command-export-shell-version.bash index 92ace8abe..07759181d 100644 --- a/lib/commands/command-export-shell-version.bash +++ b/lib/commands/command-export-shell-version.bash @@ -44,7 +44,7 @@ shell_command() { version=$(latest_command "$plugin") fi if ! (check_if_version_exists "$plugin" "$version"); then - version_not_installed_text "$plugin" "$version" 1>&2 + display_version_not_installed "$plugin" "$version" 1>&2 printf "false\n" exit 1 fi diff --git a/lib/functions/versions.bash b/lib/functions/versions.bash index 4b7cc34bc..d9fa638b0 100644 --- a/lib/functions/versions.bash +++ b/lib/functions/versions.bash @@ -53,7 +53,7 @@ version_command() { fi if ! (check_if_version_exists "$plugin_name" "$version"); then - version_not_installed_text "$plugin_name" "$version" 1>&2 + display_version_not_installed "$plugin_name" "$version" 1>&2 exit 1 fi diff --git a/lib/utils.bash b/lib/utils.bash index 8eae18fcb..e06e11e1c 100644 --- a/lib/utils.bash +++ b/lib/utils.bash @@ -137,13 +137,6 @@ check_if_version_exists() { fi } -version_not_installed_text() { - local plugin_name=$1 - local version=$2 - - printf "version %s is not installed for %s\n" "$version" "$plugin_name" -} - get_plugin_path() { if [ -n "$1" ]; then printf "%s\n" "$(asdf_data_dir)/plugins/$1" @@ -156,6 +149,18 @@ display_error() { printf "%s\n" "$1" >&2 } +display_no_version_set() { + local plugin_name=$1 + printf "No version is set for %s; please run \`asdf %s \`\n" "$plugin_name" "$plugin_name" +} + +display_version_not_installed() { + local plugin_name=$1 + local version=$2 + + printf "version %s is not installed for %s\n" "$version" "$plugin_name" +} + get_version_in_dir() { local plugin_name=$1 local search_path=$2 @@ -229,11 +234,6 @@ find_versions() { fi } -display_no_version_set() { - local plugin_name=$1 - printf "No version is set for %s; please run \`asdf %s \`\n" "$plugin_name" "$plugin_name" -} - get_version_from_env() { local plugin_name=$1 local upcase_name diff --git a/scripts/install_dependencies.bash b/scripts/install_dependencies.bash index 8965077d7..9904f6bdc 100755 --- a/scripts/install_dependencies.bash +++ b/scripts/install_dependencies.bash @@ -35,7 +35,7 @@ if [ "$RUNNER_OS" = "Linux" ]; then printf "%s\n" "Installing dependencies on Linux" curl -fsSLo- https://packages.microsoft.com/keys/microsoft.asc | sudo tee /etc/apt/trusted.gpg.d/microsoft.asc >/dev/null - sudo sh -c 'echo "deb [arch=amd64] https://packages.microsoft.com/repos/microsoft-debian-bullseye-prod bullseye main" > /etc/apt/sources.list.d/microsoft.list' + sudo sh -c 'printf "%s\n" "deb [arch=amd64] https://packages.microsoft.com/repos/microsoft-debian-bullseye-prod bullseye main" > /etc/apt/sources.list.d/microsoft.list' sudo add-apt-repository -y ppa:fish-shell/release-3 sudo apt-get update sudo apt-get -y install curl parallel \ @@ -58,7 +58,7 @@ if [ "$RUNNER_OS" = "Linux" ]; then mv nu-${nushell_semver}-x86_64-unknown-linux-gnu/* "$HOME/bin" # Add $HOME/bin to path (add Elvish & Nushell to path) - echo "$HOME/bin" >>"$GITHUB_PATH" + printf '%s\n' "$HOME/bin" >>"$GITHUB_PATH" fi ### Install dependencies on macOS @@ -75,4 +75,4 @@ fi printf "%s\n" "Installing bats-core" bats_version=$(grep -Eo "^\\s*bats\\s*.*$" ".tool-versions" | cut -d ' ' -f2-) git clone --depth 1 --branch "v$bats_version" https://github.com/bats-core/bats-core.git "$HOME/bats-core" -echo "$HOME/bats-core/bin" >>"$GITHUB_PATH" +printf '%s\n' "$HOME/bats-core/bin" >>"$GITHUB_PATH" diff --git a/test/utils.bats b/test/utils.bats index 39f29ebac..a1f0dd66f 100644 --- a/test/utils.bats +++ b/test/utils.bats @@ -70,8 +70,8 @@ teardown() { [ "$status" -eq 1 ] } -@test "version_not_installed_text is correct" { - run version_not_installed_text "dummy" "1.0.0" +@test "display_version_not_installed is correct" { + run display_version_not_installed "dummy" "1.0.0" [ "$status" -eq 0 ] [ "$output" = "version 1.0.0 is not installed for dummy" ] } From ded8785e45bc8f83e62c68f04a4e068605516e27 Mon Sep 17 00:00:00 2001 From: Edwin Kofler Date: Fri, 6 Oct 2023 02:07:05 -0700 Subject: [PATCH 3/3] refactor: Better use `display_{info,error}` functions --- bin/asdf | 16 ++++---- lib/commands/command-current.bash | 10 ++--- lib/commands/command-exec.bash | 2 +- .../command-export-shell-version.bash | 4 +- lib/commands/command-help.bash | 4 +- lib/commands/command-update.bash | 6 +-- lib/commands/command-which.bash | 2 +- lib/functions/installs.bash | 14 +++---- lib/functions/plugins.bash | 6 +-- lib/functions/versions.bash | 12 +++--- lib/utils.bash | 38 +++++++++++++------ 11 files changed, 64 insertions(+), 50 deletions(-) diff --git a/bin/asdf b/bin/asdf index 4a15f61f0..351d93848 100755 --- a/bin/asdf +++ b/bin/asdf @@ -63,7 +63,7 @@ asdf_cmd() { local ASDF_CMD_FILE args_offset if [ "shell" = "$1" ]; then - printf "Shell integration is not enabled. Please ensure you source asdf in your shell setup." >&2 + display_error "Shell integration is not enabled. Please ensure you source asdf in your shell setup." exit 1 fi @@ -96,12 +96,12 @@ asdf_cmd() { # In those cases, the path to that command is always an absolute path. However, this codepath can also be activated if a user accidentally # marks files in ./lib/commands/* as executable. This code detects when that happens and prints a useful warning message. if [[ "$ASDF_CMD_FILE" == ./lib/commands/* ]]; then - printf '%s\n' "----------" - printf '%s\n' "asdf: Warning: You are executing an asdf command from \$ASDF_DIR, but we detected that some files have been" - printf '%s\n' " erroneously marked as executable. All files under '$ASDF_DIR/lib/commands' must NOT be marked" - printf '%s\n' " as executable. Otherwise, asdf will not be able to source its core files" - printf '%s\n' "----------" - fi >&2 + display_error "----------" + display_error "asdf: Warning: You are executing an asdf command from \$ASDF_DIR, but we detected that some files have been" + display_error " erroneously marked as executable. All files under '$ASDF_DIR/lib/commands' must NOT be marked" + display_error " as executable. Otherwise, asdf will not be able to source its core files" + display_error "----------" + fi exec "$ASDF_CMD_FILE" "${@:${args_offset}}" elif [ -f "$ASDF_CMD_FILE" ]; then @@ -111,7 +111,7 @@ asdf_cmd() { else local asdf_cmd_dir asdf_cmd_dir="$(asdf_dir)/lib/commands" - printf "%s\n" "Unknown command: \`asdf ${*}\`" >&2 + display_error "Unknown command: \`asdf ${*}\`" # shellcheck source=lib/commands/command-help.bash . "$asdf_cmd_dir/command-help.bash" >&2 return 127 diff --git a/lib/commands/command-current.bash b/lib/commands/command-current.bash index 3a7a21ebf..1684c5241 100644 --- a/lib/commands/command-current.bash +++ b/lib/commands/command-current.bash @@ -30,15 +30,15 @@ plugin_current_command() { if [ -n "$version_not_installed" ]; then description="Not installed. Run \"asdf install $plugin $version\"" - printf "$terminal_format" "$plugin" "$version" "$description" 1>&2 + display_error "$terminal_format" "$plugin" "$version" "$description" return 1 elif [ -z "$full_version" ]; then description="No version is set. Run \"asdf $plugin \"" - printf "$terminal_format" "$plugin" "______" "$description" 1>&2 + display_error "$terminal_format" "$plugin" "______" "$description" return 126 else description="$version_file_path" - printf "$terminal_format" "$plugin" "$full_version" "$description" + display_info "$terminal_format" "$plugin" "$full_version" "$description" fi } @@ -75,8 +75,8 @@ check_for_deprecated_plugin() { local new_script="${plugin_path}/bin/list-legacy-filenames" if [ "$legacy_config" = "yes" ] && [ -f "$deprecated_script" ] && [ ! -f "$new_script" ]; then - printf "Heads up! It looks like your %s plugin is out of date. You can update it with:\n\n" "$plugin_name" - printf " asdf plugin-update %s\n\n" "$plugin_name" + display_info "Heads up! It looks like your %s plugin is out of date. You can update it with:\n\n" "$plugin_name" + display_info " asdf plugin-update %s\n\n" "$plugin_name" fi } diff --git a/lib/commands/command-exec.bash b/lib/commands/command-exec.bash index cb56b36c3..0e226f4f5 100644 --- a/lib/commands/command-exec.bash +++ b/lib/commands/command-exec.bash @@ -16,7 +16,7 @@ shim_exec_command() { local executable_path="$3" if [ ! -x "$executable_path" ]; then - printf "No %s executable found for %s %s\n" "$shim_name" "$plugin_name" "$version" >&2 + display_error "No %s executable found for %s %s\n" "$shim_name" "$plugin_name" "$version" exit 2 fi diff --git a/lib/commands/command-export-shell-version.bash b/lib/commands/command-export-shell-version.bash index 07759181d..605435152 100644 --- a/lib/commands/command-export-shell-version.bash +++ b/lib/commands/command-export-shell-version.bash @@ -8,7 +8,7 @@ shell_command() { shift if [ "$#" -lt "2" ]; then - printf "Usage: asdf shell {|--unset}\n" >&2 + display_error "Usage: asdf shell {|--unset}\n" printf "false\n" exit 1 fi @@ -44,7 +44,7 @@ shell_command() { version=$(latest_command "$plugin") fi if ! (check_if_version_exists "$plugin" "$version"); then - display_version_not_installed "$plugin" "$version" 1>&2 + display_version_not_installed "$plugin" "$version" >&2 printf "false\n" exit 1 fi diff --git a/lib/commands/command-help.bash b/lib/commands/command-help.bash index 77f1bb27c..2e547dc13 100644 --- a/lib/commands/command-help.bash +++ b/lib/commands/command-help.bash @@ -78,11 +78,11 @@ help_command() { (print_plugin_help "$plugin_path") fi else - printf "No documentation for plugin %s\n" "$plugin_name" >&2 + display_error "No documentation for plugin %s\n" "$plugin_name" exit 1 fi else - printf "No plugin named %s\n" "$plugin_name" >&2 + display_error "No plugin named %s\n" "$plugin_name" exit 1 fi else diff --git a/lib/commands/command-update.bash b/lib/commands/command-update.bash index f9912645f..b5bc20807 100644 --- a/lib/commands/command-update.bash +++ b/lib/commands/command-update.bash @@ -7,7 +7,7 @@ update_command() { cd "$(asdf_dir)" || exit 1 if [ -f asdf_updates_disabled ] || ! git rev-parse --is-inside-work-tree &>/dev/null; then - printf "Update command disabled. Please use the package manager that you used to install asdf to upgrade asdf.\n" + display_info "Update command disabled. Please use the package manager that you used to install asdf to upgrade asdf." exit 42 else do_update "$update_to_head" @@ -23,7 +23,7 @@ do_update() { git fetch origin master git checkout master git reset --hard origin/master - printf "Updated asdf to latest on the master branch\n" + display_info "Updated asdf to latest on the master branch" else # Update to latest release git fetch origin --tags || exit 1 @@ -38,7 +38,7 @@ do_update() { # Update git checkout "$tag" || exit 1 - printf "Updated asdf to release %s\n" "$tag" + display_info "Updated asdf to release %s\n" "$tag" fi } diff --git a/lib/commands/command-which.bash b/lib/commands/command-which.bash index 8696dbf3e..786bf6aaf 100644 --- a/lib/commands/command-which.bash +++ b/lib/commands/command-which.bash @@ -15,7 +15,7 @@ which_command() { local executable_path="$3" if [ ! -x "$executable_path" ]; then - printf "No %s executable found for %s %s\n" "$shim_name" "$plugin_name" "$version" >&2 + display_error "No %s executable found for %s %s\n" "$shim_name" "$plugin_name" "$version" exit 1 fi diff --git a/lib/functions/installs.bash b/lib/functions/installs.bash index 721ae50c4..54e16433b 100644 --- a/lib/functions/installs.bash +++ b/lib/functions/installs.bash @@ -67,7 +67,7 @@ install_one_local_tool() { install_tool_version "$plugin_name" "$plugin_version" done else - printf "No versions specified for %s in config files or environment\n" "$plugin_name" + display_info "No versions specified for %s in config files or environment\n" "$plugin_name" exit 1 fi } @@ -97,7 +97,7 @@ install_local_tool_versions() { fi if [ -z "$plugins_installed" ]; then - printf "Install plugins first to be able to install tools\n" + display_info "Install plugins first to be able to install tools" exit 1 fi @@ -107,7 +107,7 @@ install_local_tool_versions() { tools_file=$(strip_tool_version_comments "$tool_versions_path" | cut -d ' ' -f 1) for plugin_name in $tools_file; do if ! printf '%s\n' "${plugins_installed[@]}" | grep -q "^$plugin_name\$"; then - printf "%s plugin is not installed\n" "$plugin_name" + display_info "%s plugin is not installed\n" "$plugin_name" some_plugin_not_installed='yes' fi done @@ -134,9 +134,9 @@ install_local_tool_versions() { fi if [ -z "$some_tools_installed" ]; then - printf "Either specify a tool & version in the command\n" - printf "OR add .tool-versions file in this directory\n" - printf "or in a parent directory\n" + display_info "Either specify a tool & version in the command" + display_info "OR add .tool-versions file in this directory" + display_info "or in a parent directory" exit 1 fi } @@ -192,7 +192,7 @@ install_tool_version() { trap 'handle_cancel $install_path' INT if [ -d "$install_path" ]; then - printf "%s %s is already installed\n" "$plugin_name" "$full_version" + display_info "%s %s is already installed\n" "$plugin_name" "$full_version" else if [ -f "${plugin_path}/bin/download" ]; then diff --git a/lib/functions/plugins.bash b/lib/functions/plugins.bash index 3b36ddd9c..5f7c1fdcb 100644 --- a/lib/functions/plugins.bash +++ b/lib/functions/plugins.bash @@ -79,7 +79,7 @@ plugin_add_command() { mkdir -p "$(asdf_data_dir)/plugins" if [ -d "$plugin_path" ]; then - printf '%s\n' "Plugin named $plugin_name already added" + display_info "Plugin named $plugin_name already added" exit 0 else asdf_run_hook "pre_asdf_plugin_add" "$plugin_name" @@ -140,11 +140,11 @@ update_plugin() { local prev_ref= local post_ref= { - printf "Location of %s plugin: %s\n" "$plugin_name" "$plugin_path" + display_info "Location of %s plugin: %s\n" "$plugin_name" "$plugin_path" asdf_run_hook "pre_asdf_plugin_update" "$plugin_name" asdf_run_hook "pre_asdf_plugin_update_${plugin_name}" - printf "Updating %s to %s\n" "$plugin_name" "$gitref" + display_info "Updating %s to %s\n" "$plugin_name" "$gitref" git "${common_git_options[@]}" fetch --prune --update-head-ok origin "$gitref:$gitref" prev_ref=$(git "${common_git_options[@]}" rev-parse --short HEAD) diff --git a/lib/functions/versions.bash b/lib/functions/versions.bash index d9fa638b0..185e8f749 100644 --- a/lib/functions/versions.bash +++ b/lib/functions/versions.bash @@ -53,7 +53,7 @@ version_command() { fi if ! (check_if_version_exists "$plugin_name" "$version"); then - display_version_not_installed "$plugin_name" "$version" 1>&2 + display_version_not_installed "$plugin_name" "$version" >&2 exit 1 fi @@ -99,9 +99,9 @@ list_all_command() { if [[ $return_code -ne 0 ]]; then # Printing all output to allow plugin to handle error formatting - printf "Plugin %s's list-all callback script failed with output:\n" "${plugin_name}" >&2 - printf "%s\n" "$(cat "$std_err_file")" >&2 - printf "%s\n" "$(cat "$std_out_file")" >&2 + display_error "Plugin %s's list-all callback script failed with output:\n" "${plugin_name}" + display_error "%s\n" "$(cat "$std_err_file")" + display_error "%s\n" "$(cat "$std_out_file")" rm "$std_out_file" "$std_err_file" exit 1 fi @@ -151,7 +151,7 @@ latest_command() { versions=$("${plugin_path}"/bin/latest-stable "$query") if [ -z "${versions}" ]; then # this branch requires this print to mimic the error from the list-all branch - printf "No compatible versions available (%s %s)\n" "$plugin_name" "$query" >&2 + display_error "No compatible versions available (%s %s)\n" "$plugin_name" "$query" exit 1 fi else @@ -208,7 +208,7 @@ latest_all() { printf "%s\t%s\t%s\n" "$plugin_name" "$version" "$installed_status" done else - printf "%s\n" 'No plugins installed' + display_info 'No plugins installed' fi exit 0 } diff --git a/lib/utils.bash b/lib/utils.bash index e06e11e1c..7439f5ba7 100644 --- a/lib/utils.bash +++ b/lib/utils.bash @@ -146,7 +146,21 @@ get_plugin_path() { } display_error() { - printf "%s\n" "$1" >&2 + if (($# == 1)); then + set -- '%s\n' "$@" + fi + + # shellcheck disable=SC2059 + printf "$@" >&2 # checkstyle-ignore +} + +display_info() { + if (($# == 1)); then + set -- '%s\n' "$@" + fi + + # shellcheck disable=SC2059 + printf "$@" } display_no_version_set() { @@ -426,7 +440,7 @@ initialize_or_update_plugin_repository() { disable_plugin_short_name_repo="$(get_asdf_config_value "disable_plugin_short_name_repository")" if [ "yes" = "$disable_plugin_short_name_repo" ]; then - printf "Short-name plugin repository is disabled\n" >&2 + display_error "Short-name plugin repository is disabled" exit 1 fi @@ -646,7 +660,7 @@ shim_plugin_versions() { if [ -x "$shim_path" ]; then grep "# asdf-plugin: " "$shim_path" 2>/dev/null | sed -e "s/# asdf-plugin: //" | uniq else - printf "asdf: unknown shim %s\n" "$executable_name" + display_info "asdf: unknown shim %s\n" "$executable_name" return 1 fi } @@ -659,7 +673,7 @@ shim_plugins() { if [ -x "$shim_path" ]; then grep "# asdf-plugin: " "$shim_path" 2>/dev/null | sed -e "s/# asdf-plugin: //" | cut -d' ' -f 1 | uniq else - printf "asdf: unknown shim %s\n" "$executable_name" + display_info "asdf: unknown shim %s\n" "$executable_name" return 1 fi } @@ -761,7 +775,7 @@ with_shim_executable() { local shim_exec="${2}" if [ ! -f "$(asdf_data_dir)/shims/${shim_name}" ]; then - printf "%s %s %s\n" "unknown command:" "${shim_name}." "Perhaps you have to reshim?" >&2 + display_error "%s %s %s\n" "unknown command:" "${shim_name}." "Perhaps you have to reshim?" return 1 fi @@ -820,15 +834,15 @@ with_shim_executable() { done if [ -n "${preset_plugin_versions[*]}" ]; then - printf "%s %s\n" "No preset version installed for command" "$shim_name" - printf "%s\n\n" "Please install a version by running one of the following:" + display_info "%s %s\n" "No preset version installed for command" "$shim_name" + display_info "%s\n\n" "Please install a version by running one of the following:" for preset_plugin_version in "${preset_plugin_versions[@]}"; do - printf "%s %s\n" "asdf install" "$preset_plugin_version" + display_info "%s %s\n" "asdf install" "$preset_plugin_version" done - printf "\n%s %s\n" "or add one of the following versions in your config file at" "$closest_tool_version" + display_info "\n%s %s\n" "or add one of the following versions in your config file at" "$closest_tool_version" else - printf "%s %s\n" "No version is set for command" "$shim_name" - printf "%s %s\n" "Consider adding one of the following versions in your config file at" "$closest_tool_version" + display_info "%s %s\n" "No version is set for command" "$shim_name" + display_info "%s %s\n" "Consider adding one of the following versions in your config file at" "$closest_tool_version" fi shim_plugin_versions "${shim_name}" ) >&2 @@ -872,7 +886,7 @@ util_validate_no_carriage_returns() { local file_path="$1" if grep -qr $'\r' "$file_path"; then - printf '%s\n' "asdf: Warning: File $file_path contains carriage returns. Please remove them." >&2 + display_error "asdf: Warning: File $file_path contains carriage returns. Please remove them." fi }