fix: version parsing and SSH config comment/quote handling
Replace sed 's/[^0-9.]//g' with grep -oE for semver extraction — fixes breakage on Apple Git suffix and rc versions. Add strip_ssh_value() helper to strip inline comments and surrounding quotes from SSH config values. Applied to IdentityFile scanning, audit_ssh_directive, and apply_ssh_directive. 9 new tests (62 total). Closes: #8 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -65,6 +65,24 @@ die() {
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Strip inline comments and surrounding quotes from an SSH config value.
|
||||
# Handles: value # comment, "value", 'value', "value" # comment
|
||||
strip_ssh_value() {
|
||||
local val="$1"
|
||||
# Remove inline comment (not inside quotes): strip ' #...' from end
|
||||
# Be careful: only strip ' #' preceded by space (not part of path)
|
||||
val="$(printf '%s' "$val" | sed 's/[[:space:]]#.*$//')"
|
||||
# Remove surrounding double quotes
|
||||
val="${val#\"}"
|
||||
val="${val%\"}"
|
||||
# Remove surrounding single quotes
|
||||
val="${val#\'}"
|
||||
val="${val%\'}"
|
||||
# Trim whitespace
|
||||
val="$(printf '%s' "$val" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')"
|
||||
printf '%s' "$val"
|
||||
}
|
||||
|
||||
print_ok() {
|
||||
printf '%b[OK]%b %s\n' "$GREEN" "$RESET" "$1" >&2
|
||||
AUDIT_OK=$((AUDIT_OK + 1))
|
||||
@@ -209,7 +227,10 @@ check_dependencies() {
|
||||
fi
|
||||
|
||||
local git_version
|
||||
git_version="$(git --version | sed 's/[^0-9.]//g')"
|
||||
git_version="$(git --version | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1)"
|
||||
if [ -z "$git_version" ]; then
|
||||
die "Could not parse git version from: $(git --version)"
|
||||
fi
|
||||
if ! version_gte "$git_version" "2.34.0"; then
|
||||
die "git >= 2.34.0 required (found $git_version)"
|
||||
fi
|
||||
@@ -395,6 +416,7 @@ audit_ssh_directive() {
|
||||
|
||||
local current
|
||||
current="$(grep -i "^[[:space:]]*${directive}[[:space:]]" "$SSH_CONFIG" 2>/dev/null | head -1 | sed 's/^[[:space:]]*[^ ]*[[:space:]]*//' || true)"
|
||||
current="$(strip_ssh_value "$current")"
|
||||
|
||||
if [ -z "$current" ]; then
|
||||
print_miss "SSH: $directive (expected: $expected)"
|
||||
@@ -615,11 +637,11 @@ detect_existing_keys() {
|
||||
if [ -f "$SSH_CONFIG" ]; then
|
||||
local identity_path
|
||||
while IFS= read -r identity_path; do
|
||||
# Strip inline comments and quotes
|
||||
identity_path="$(strip_ssh_value "$identity_path")"
|
||||
[ -z "$identity_path" ] && continue
|
||||
# Expand tilde safely
|
||||
identity_path="${identity_path/#\~/$HOME}"
|
||||
# Strip leading/trailing whitespace
|
||||
identity_path="$(printf '%s' "$identity_path" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')"
|
||||
[ -z "$identity_path" ] && continue
|
||||
|
||||
pub_path="${identity_path}.pub"
|
||||
if [ -f "$pub_path" ]; then
|
||||
@@ -827,6 +849,7 @@ apply_ssh_directive() {
|
||||
# Check if directive already exists with correct value (case-insensitive directive match)
|
||||
local current
|
||||
current="$(grep -i "^[[:space:]]*${directive}[[:space:]]" "$SSH_CONFIG" 2>/dev/null | head -1 | sed 's/^[[:space:]]*[^ ]*[[:space:]]*//' || true)"
|
||||
current="$(strip_ssh_value "$current")"
|
||||
|
||||
if [ "$current" = "$value" ]; then
|
||||
return
|
||||
|
||||
@@ -108,6 +108,60 @@ source_functions() {
|
||||
assert_failure
|
||||
}
|
||||
|
||||
# ===========================================================================
|
||||
# Version extraction (grep-based, not sed)
|
||||
# ===========================================================================
|
||||
|
||||
@test "version extraction handles standard git output" {
|
||||
local ver
|
||||
ver="$(echo "git version 2.39.5" | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1)"
|
||||
[ "$ver" = "2.39.5" ]
|
||||
}
|
||||
|
||||
@test "version extraction handles Apple Git suffix" {
|
||||
local ver
|
||||
ver="$(echo "git version 2.39.5 (Apple Git-154)" | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1)"
|
||||
[ "$ver" = "2.39.5" ]
|
||||
}
|
||||
|
||||
@test "version extraction handles rc suffix" {
|
||||
local ver
|
||||
ver="$(echo "git version 2.45.0-rc1" | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1)"
|
||||
[ "$ver" = "2.45.0" ]
|
||||
}
|
||||
|
||||
# ===========================================================================
|
||||
# strip_ssh_value helper
|
||||
# ===========================================================================
|
||||
|
||||
@test "strip_ssh_value removes inline comment" {
|
||||
source_functions
|
||||
local result
|
||||
result="$(strip_ssh_value "~/.ssh/id_ed25519 # signing key")"
|
||||
[ "$result" = "~/.ssh/id_ed25519" ]
|
||||
}
|
||||
|
||||
@test "strip_ssh_value removes surrounding double quotes" {
|
||||
source_functions
|
||||
local result
|
||||
result="$(strip_ssh_value '"~/.ssh/my key"')"
|
||||
[ "$result" = "~/.ssh/my key" ]
|
||||
}
|
||||
|
||||
@test "strip_ssh_value removes quotes and comment together" {
|
||||
source_functions
|
||||
local result
|
||||
result="$(strip_ssh_value '"~/.ssh/my key" # comment')"
|
||||
[ "$result" = "~/.ssh/my key" ]
|
||||
}
|
||||
|
||||
@test "strip_ssh_value handles plain value" {
|
||||
source_functions
|
||||
local result
|
||||
result="$(strip_ssh_value "accept-new")"
|
||||
[ "$result" = "accept-new" ]
|
||||
}
|
||||
|
||||
# ===========================================================================
|
||||
# Audit: git config settings
|
||||
# ===========================================================================
|
||||
@@ -493,6 +547,36 @@ SSHEOF
|
||||
[ "$SIGNING_PUB_PATH" = "${TEST_HOME}/.ssh/my_custom_key.pub" ]
|
||||
}
|
||||
|
||||
@test "detect_existing_keys handles IdentityFile with inline comment" {
|
||||
ssh-keygen -t ed25519 -f "${TEST_HOME}/.ssh/my_key" -N "" -q
|
||||
|
||||
cat > "${TEST_HOME}/.ssh/config" <<SSHEOF
|
||||
Host github.com
|
||||
IdentityFile ${TEST_HOME}/.ssh/my_key # signing key
|
||||
SSHEOF
|
||||
|
||||
source_functions
|
||||
detect_existing_keys
|
||||
|
||||
[ "$SIGNING_KEY_FOUND" = true ]
|
||||
[ "$SIGNING_PUB_PATH" = "${TEST_HOME}/.ssh/my_key.pub" ]
|
||||
}
|
||||
|
||||
@test "detect_existing_keys handles quoted IdentityFile path" {
|
||||
ssh-keygen -t ed25519 -f "${TEST_HOME}/.ssh/my_key" -N "" -q
|
||||
|
||||
cat > "${TEST_HOME}/.ssh/config" <<SSHEOF
|
||||
Host github.com
|
||||
IdentityFile "${TEST_HOME}/.ssh/my_key"
|
||||
SSHEOF
|
||||
|
||||
source_functions
|
||||
detect_existing_keys
|
||||
|
||||
[ "$SIGNING_KEY_FOUND" = true ]
|
||||
[ "$SIGNING_PUB_PATH" = "${TEST_HOME}/.ssh/my_key.pub" ]
|
||||
}
|
||||
|
||||
@test "detect_existing_keys finds configured key via user.signingkey" {
|
||||
ssh-keygen -t ed25519 -f "${TEST_HOME}/.ssh/signing_key" -N "" -q
|
||||
git config --global user.signingkey "${TEST_HOME}/.ssh/signing_key.pub"
|
||||
|
||||
Reference in New Issue
Block a user