From 4d55c8b8bbbc90485e9b372d05cee6de92fcaeb5 Mon Sep 17 00:00:00 2001 From: Daniel Arroyo Date: Wed, 9 Sep 2026 11:19:13 -0300 Subject: [PATCH] fix: parse SSH config entries with tabs as well as spaces resolve_ssh_alias() now extracts tokens with 'read -r', which collapses tabs and spaces uniformly. Two bugs were at play: 1. The previous parser split on literal spaces (key="${line%% *}") and used '${line#Host }' to drop the Host directive, so configs that used tab indentation (e.g. '\tHostName 10.60.16.35') ended up with key being the whole line and never matching the case branches. Result: 'has no HostName in ~/.ssh/config' even when one was present. 2. The script's global IFS is $'\n\t' (no space), which made 'read' unable to split on spaces at all. Fixed by restoring space-aware IFS locally inside the loop. Verified against tabbed, spaced, mixed, indented-comment and Host\tname configs; behavior with the original space-separated configs is unchanged. --- scripts/build-and-push.sh | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/scripts/build-and-push.sh b/scripts/build-and-push.sh index f380407..a901c51 100755 --- a/scripts/build-and-push.sh +++ b/scripts/build-and-push.sh @@ -130,15 +130,19 @@ resolve_ssh_alias() { [[ -f "$config" ]] \ || die "Cannot resolve '$alias': $config not found and value has no '@'." - local in_block=0 hostname="" user="" port="" identity="" line key value p + local in_block=0 hostname="" user="" port="" identity="" line first p local -a patterns - while IFS= read -r line || [[ -n "$line" ]]; do - line="${line#"${line%%[![:space:]]*}"}" - [[ -z "$line" || "${line:0:1}" == "#" ]] && continue - key="${line%% *}" - if [[ "$key" == "Host" ]]; then + # Force whitespace-aware splitting (the script's global IFS excludes spaces). + local IFS=$' \t\n' + while read -r line || [[ -n "$line" ]]; do + # First whitespace-separated token (tabs and spaces collapse uniformly). + read -r first _ <<< "$line" + [[ -z "$first" || "$first" == "#" ]] && continue + + if [[ "$first" == "Host" ]]; then if (( in_block )); then break; fi - read -r -a patterns <<< "${line#Host }" + read -r -a patterns <<< "$line" + patterns=("${patterns[@]:1}") in_block=0 for p in "${patterns[@]}"; do if [[ "$p" == "$alias" ]]; then @@ -149,12 +153,13 @@ resolve_ssh_alias() { done continue fi + if (( in_block )); then - case "$key" in - HostName) hostname="${line#* }" ;; - User) user="${line#* }" ;; - Port) port="${line#* }" ;; - IdentityFile) identity="${line#* }" ;; + case "$first" in + HostName) read -r _ hostname <<< "$line" ;; + User) read -r _ user <<< "$line" ;; + Port) read -r _ port <<< "$line" ;; + IdentityFile) read -r _ identity <<< "$line" ;; esac fi done < "$config"