diff --git a/b.sh b/b.sh index d380330..8160689 100755 --- a/b.sh +++ b/b.sh @@ -1,3 +1,4 @@ +# shellcheck shell=bash # >>> bootstrap-cli b function >>> # Shortcut for downloading and running bootstrap/install scripts b() { @@ -19,6 +20,7 @@ b() { _version_lt() { [ "$1" = "$2" ] && return 1 local IFS=. + # shellcheck disable=SC2206 local i ver1=($1) ver2=($2) for ((i=${#ver1[@]}; i<3; i++)); do ver1[i]=0; done for ((i=${#ver2[@]}; i<3; i++)); do ver2[i]=0; done @@ -41,7 +43,7 @@ b() { local base_url="https://git.adityagupta.dev/sortedcord/bootstrap/raw/branch/master" local local_ver="0.0.0" - [ -f "$routes_dir/VERSION" ] && local_ver=$(cat "$routes_dir/VERSION" 2>/dev/null | tr -d '[:space:]') + [ -f "$routes_dir/VERSION" ] && local_ver=$(tr -d '[:space:]' < "$routes_dir/VERSION" 2>/dev/null) local remote_ver if remote_ver=$(curl -fsSL "$base_url/VERSION" 2>/dev/null); then @@ -71,6 +73,7 @@ b() { # Sourced again in the parent shell after successfully running the command if [ $ret -eq 0 ]; then if [ -f "$HOME/.bashrc" ]; then + # shellcheck source=/dev/null . "$HOME/.bashrc" fi fi @@ -123,6 +126,7 @@ _b_completion() { return 0 fi + # shellcheck disable=SC2207 COMPREPLY=( $(compgen -W "$opts" -- "$cur") ) return 0 fi @@ -161,6 +165,7 @@ _b_completion() { return 0 fi + # shellcheck disable=SC2207 COMPREPLY=( $(compgen -W "$installer_keys" -- "$cur") ) return 0 fi @@ -170,6 +175,7 @@ _b_completion() { # List of directories in ~/.config/ to choose from local config_dirs config_dirs=$(find "$HOME/.config" -mindepth 1 -maxdepth 1 -type d -exec basename {} \; 2>/dev/null) + # shellcheck disable=SC2207 COMPREPLY=( $(compgen -W "$config_dirs" -- "$cur") ) return 0 fi diff --git a/bootstrap.sh b/bootstrap.sh index 53ab262..db8d966 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -20,7 +20,7 @@ fi # Locate or download libraries so that sourced installers can use them BOOTSTRAP_DIR="${BOOTSTRAP_DIR:-$HOME/.config/bootstrap}" -_SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd 2>/dev/null || pwd)" +_SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd 2>/dev/null)" || _SCRIPT_DIR="$(pwd)" if [ -f "$_SCRIPT_DIR/lib/common.sh" ]; then # Dev/local mode: source directly from repo @@ -268,7 +268,7 @@ EOF # Display centered version of bootstrap in bold _version="" if [ -f "$_version_file" ]; then - _version=$(cat "$_version_file" | tr -d '\r\n') + _version=$(tr -d '\r\n' < "$_version_file") fi if [ -z "$_version" ]; then _version="0.0.0" # Fallback if VERSION missing @@ -335,6 +335,7 @@ EOF # Load the b function immediately in the current subshell if [ -f "$HOME/.config/bootstrap/b.sh" ]; then + # shellcheck source=/dev/null . "$HOME/.config/bootstrap/b.sh" fi @@ -347,6 +348,7 @@ else # Sourced mode (e.g., when sourced by installers or manually by user) # Load the b function in the current shell context if [ -f "$HOME/.config/bootstrap/b.sh" ]; then + # shellcheck source=/dev/null . "$HOME/.config/bootstrap/b.sh" fi fi diff --git a/commands/con.sh b/commands/con.sh index 0d5e797..798be76 100644 --- a/commands/con.sh +++ b/commands/con.sh @@ -1,3 +1,4 @@ +# shellcheck shell=bash # Command: con # Edits configurations in ~/.config/ diff --git a/commands/help.sh b/commands/help.sh index 1e216c3..70fc156 100644 --- a/commands/help.sh +++ b/commands/help.sh @@ -1,3 +1,4 @@ +# shellcheck shell=bash # Command: help # Lists all available bootstrap commands and installers diff --git a/commands/uninstall.sh b/commands/uninstall.sh index a4934aa..fe2cc40 100644 --- a/commands/uninstall.sh +++ b/commands/uninstall.sh @@ -1,3 +1,4 @@ +# shellcheck shell=bash # Command: uninstall (gone) # Removes bootstrap CLI and cleans up shell configuration files @@ -45,7 +46,6 @@ if [ -f "$HOME/.bash_aliases" ]; then # 2. Remove specific aliases added by bootstrap (e.g. vim -> nvim) if grep -q '^alias vim="nvim"$' "$HOME/.bash_aliases" 2>/dev/null; then - local tmp_file tmp_file=$(mktemp) sed '/^alias vim="nvim"$/d' "$HOME/.bash_aliases" > "$tmp_file" cat "$tmp_file" > "$HOME/.bash_aliases" @@ -61,7 +61,6 @@ fi # If force is false, leave a lightweight 'b back' shortcut function in shell config files if [ "$FORCE" = "false" ]; then - local b_back_content b_back_content=$(cat << 'EOF' b() { if [ "${1:-}" = "back" ]; then diff --git a/commands/up.sh b/commands/up.sh index 32f0bf4..d9103d4 100644 --- a/commands/up.sh +++ b/commands/up.sh @@ -1,9 +1,11 @@ +# shellcheck shell=bash # Command: up # Manually checks for updates and runs the updater if a newer version is found. # Source libraries if needed if [ -z "${_LIB_COMMON_SOURCED:-}" ]; then _LIB_DIR="${BOOTSTRAP_DIR:-$HOME/.config/bootstrap}/lib" + # shellcheck source=/dev/null . "$_LIB_DIR/common.sh" fi @@ -14,7 +16,7 @@ log_info "Checking for updates..." local_ver="0.0.0" version_file="${BOOTSTRAP_DIR:-$HOME/.config/bootstrap}/VERSION" if [ -f "$version_file" ]; then - local_ver=$(cat "$version_file" | tr -d '[:space:]') + local_ver=$(tr -d '[:space:]' < "$version_file") fi base_url="https://git.adityagupta.dev/sortedcord/bootstrap/raw/branch/master" diff --git a/installers/install_lazygit.sh b/installers/install_lazygit.sh index ed52d77..6d87bcd 100755 --- a/installers/install_lazygit.sh +++ b/installers/install_lazygit.sh @@ -34,7 +34,8 @@ install_lazygit() { local version="${latest_tag#v}" - local arch=$(detect_arch) + local arch + arch=$(detect_arch) local arch_str="x86_64" if [ "$arch" = "arm64" ]; then arch_str="arm64" diff --git a/installers/install_node.sh b/installers/install_node.sh index f730527..203b815 100644 --- a/installers/install_node.sh +++ b/installers/install_node.sh @@ -69,6 +69,7 @@ install_node() { if [ -s "$BOOTSTRAP_RUNTIMES/nvm/nvm.sh" ]; then # Temporarily disable nounset as nvm.sh does not support set -u set +u + # shellcheck source=/dev/null . "$BOOTSTRAP_RUNTIMES/nvm/nvm.sh" else log_error "Could not load NVM to install Node.js." @@ -97,7 +98,7 @@ main() { if has_command node; then log_success "Node.js (via NVM) installation and configuration complete." log_info "Installed Node version: $(node --version)" - log_info "Installed NVM version: $(nvm --version 2>/dev/null || cat "$BOOTSTRAP_RUNTIMES/nvm/package.json" | grep '"version":' | head -n1 | sed -E 's/.*"version": "([^"]+)".*/\1/' || echo "unknown")" + log_info "Installed NVM version: $(nvm --version 2>/dev/null || grep '"version":' "$BOOTSTRAP_RUNTIMES/nvm/package.json" | head -n1 | sed -E 's/.*"version": "([^"]+)".*/\1/' || echo "unknown")" else log_success "Installation complete." fi diff --git a/installers/install_nvim.sh b/installers/install_nvim.sh index 12f3ac3..8b2c66e 100644 --- a/installers/install_nvim.sh +++ b/installers/install_nvim.sh @@ -1,4 +1,5 @@ #!/usr/bin/env bash +# shellcheck disable=SC2016 # Tool: nvim # DisplayName: Neovim # Description: Install Neovim 0.12.0 and configuration diff --git a/installers/install_rust.sh b/installers/install_rust.sh index a5eb901..55fff9c 100644 --- a/installers/install_rust.sh +++ b/installers/install_rust.sh @@ -1,4 +1,5 @@ #!/usr/bin/env bash +# shellcheck disable=SC2016 # Tool: rust # DisplayName: Rust # Description: Install Rustup and Rust compiler/toolchain diff --git a/installers/install_starship.sh b/installers/install_starship.sh index f84e9f0..1075760 100644 --- a/installers/install_starship.sh +++ b/installers/install_starship.sh @@ -1,4 +1,5 @@ #!/usr/bin/env bash +# shellcheck disable=SC2016 # Tool: starship # DisplayName: Starship # Description: Install Starship shell prompt diff --git a/installers/install_uv.sh b/installers/install_uv.sh index ff14677..117b42b 100644 --- a/installers/install_uv.sh +++ b/installers/install_uv.sh @@ -1,4 +1,5 @@ #!/usr/bin/env bash +# shellcheck disable=SC2016 # Tool: uv # DisplayName: uv # Description: Fast Python package installer and resolver diff --git a/installers/install_zoxide.sh b/installers/install_zoxide.sh index 6428906..560687c 100755 --- a/installers/install_zoxide.sh +++ b/installers/install_zoxide.sh @@ -1,4 +1,5 @@ #!/usr/bin/env bash +# shellcheck disable=SC2016 # Tool: zoxide # DisplayName: Zoxide # Description: Install Zoxide directory jumper diff --git a/lib/common.sh b/lib/common.sh index 10d1151..271de45 100644 --- a/lib/common.sh +++ b/lib/common.sh @@ -81,6 +81,7 @@ make_temp_dir() { version_lt() { [ "$1" = "$2" ] && return 1 local IFS=. + # shellcheck disable=SC2206 local i ver1=($1) ver2=($2) for ((i=${#ver1[@]}; i<3; i++)); do ver1[i]=0; done for ((i=${#ver2[@]}; i<3; i++)); do ver2[i]=0; done diff --git a/lib/platform.sh b/lib/platform.sh index 9cd8a10..b646133 100644 --- a/lib/platform.sh +++ b/lib/platform.sh @@ -11,6 +11,7 @@ if [ -z "${_LIB_COMMON_SOURCED:-}" ]; then # Assumes common.sh is in the same directory as platform.sh # We resolve the directory of the current script _LIB_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + # shellcheck source=/dev/null . "$_LIB_DIR/common.sh" fi diff --git a/lib/plugins.sh b/lib/plugins.sh index bd44d6d..7abcf60 100644 --- a/lib/plugins.sh +++ b/lib/plugins.sh @@ -57,7 +57,7 @@ EOF for temp_file in "${temp_manifests[@]}"; do if [ -s "$temp_file" ]; then - cat "$temp_file" | parse_plugin_manifest >> "$cache_file" + parse_plugin_manifest < "$temp_file" >> "$cache_file" fi rm -f "$temp_file" done @@ -131,7 +131,7 @@ run_plugin() { if [ -n "$compat_ver" ]; then local current_ver="0.0.0" if [ -f "$BOOTSTRAP_DIR/VERSION" ]; then - current_ver=$(cat "$BOOTSTRAP_DIR/VERSION" | tr -d '[:space:]') + current_ver=$(tr -d '[:space:]' < "$BOOTSTRAP_DIR/VERSION") fi if version_lt "$compat_ver" "$current_ver"; then log_warn "Plugin '$plugin_name' is only tested up to bootstrap version $compat_ver (current: $current_ver). It may be incompatible." diff --git a/lib/registry.sh b/lib/registry.sh index d465f00..82a8eea 100644 --- a/lib/registry.sh +++ b/lib/registry.sh @@ -1,3 +1,5 @@ +# shellcheck shell=bash +# shellcheck disable=SC2034 # This file is auto-generated by scripts/generate_registry.sh. Do not edit manually. declare -A INSTALLERS=( diff --git a/lib/routes.sh b/lib/routes.sh index 632b931..0e51db5 100755 --- a/lib/routes.sh +++ b/lib/routes.sh @@ -262,7 +262,7 @@ for script in "${SCRIPTS[@]}"; do fi ;; fall) - local savepoint_name="${1:-}" + savepoint_name="${1:-}" if [ -z "$savepoint_name" ]; then log_error "Usage: b fall " exit 1 @@ -271,7 +271,7 @@ for script in "${SCRIPTS[@]}"; do exit 0 ;; rb) - local target="${1:-}" + target="${1:-}" if [ -z "$target" ]; then rollback_bare else @@ -283,7 +283,7 @@ for script in "${SCRIPTS[@]}"; do uninstall_tool "$t" done else - local registry_file="$BOOTSTRAP_STATE_DIR/registry.json" + registry_file="$BOOTSTRAP_STATE_DIR/registry.json" if [ -f "$registry_file" ] && jq -e --arg t "$target" '.tools | has($t)' "$registry_file" >/dev/null; then uninstall_tool "$target" else diff --git a/lib/shell_config.sh b/lib/shell_config.sh index acf6632..028ab9f 100644 --- a/lib/shell_config.sh +++ b/lib/shell_config.sh @@ -9,6 +9,7 @@ _LIB_SHELL_CONFIG_SOURCED=1 # Source common utilities if not already loaded if [ -z "${_LIB_COMMON_SOURCED:-}" ]; then _LIB_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + # shellcheck source=/dev/null . "$_LIB_DIR/common.sh" fi @@ -170,6 +171,7 @@ create_fd_symlink() { source_bashrc() { if [ -f "$HOME/.bashrc" ]; then log_info "Re-sourcing ~/.bashrc..." + # shellcheck source=/dev/null . "$HOME/.bashrc" fi } diff --git a/plugins/todo.sh b/plugins/todo.sh index f9dc0e1..e146e86 100644 --- a/plugins/todo.sh +++ b/plugins/todo.sh @@ -98,7 +98,7 @@ main() { log_success "Removed task #$task_num." ;; clear) - > "$TODO_FILE" + true > "$TODO_FILE" log_success "Cleared all tasks from your todo list." ;; --help|-h) diff --git a/scripts/generate_registry.sh b/scripts/generate_registry.sh index e3cbf99..74933d2 100755 --- a/scripts/generate_registry.sh +++ b/scripts/generate_registry.sh @@ -32,29 +32,31 @@ for f in "$INSTALLERS_DIR"/install_*.sh; do done # Sort keys alphabetically -sorted_keys=($(printf '%s\n' "${keys[@]}" | sort)) +mapfile -t sorted_keys < <(printf '%s\n' "${keys[@]}" | sort) { + echo "# shellcheck shell=bash" + echo "# shellcheck disable=SC2034" echo "# This file is auto-generated by scripts/generate_registry.sh. Do not edit manually." echo "" echo "declare -A INSTALLERS=(" for k in "${sorted_keys[@]}"; do # Escape any double quotes in description - escaped_desc=$(echo "${tools_desc[$k]}" | sed 's/"/\\"/g') + escaped_desc="${tools_desc[$k]//\"/\\\"}" echo " [$k]=\"$escaped_desc\"" done echo ")" echo "" echo "declare -A INSTALLER_DISPLAYS=(" for k in "${sorted_keys[@]}"; do - escaped_disp=$(echo "${tools_disp[$k]}" | sed 's/"/\\"/g') + escaped_disp="${tools_disp[$k]//\"/\\\"}" echo " [$k]=\"$escaped_disp\"" done echo ")" echo "" echo "declare -A INSTALLER_STRATEGIES=(" for k in "${sorted_keys[@]}"; do - escaped_strat=$(echo "${tools_strat[$k]}" | sed 's/"/\\"/g') + escaped_strat="${tools_strat[$k]//\"/\\\"}" echo " [$k]=\"$escaped_strat\"" done echo ")"