From 6ba82b1c97f30bec5fde24598cdb666462707df3 Mon Sep 17 00:00:00 2001 From: Gu1llaum-3 Date: Fri, 10 Oct 2025 21:47:13 +0200 Subject: [PATCH] feat: filter non-SSH files from config parsing - Skip README, .git, and documentation files during SSH config parsing - Add QuickHostExists for fast host validation without full parsing - Prevent errors when Include * encounters non-config files --- cmd/root.go | 19 +--- internal/config/ssh.go | 206 ++++++++++++++++++++++++++++++++++++ internal/config/ssh_test.go | 146 +++++++++++++++++++++++++ 3 files changed, 357 insertions(+), 14 deletions(-) diff --git a/cmd/root.go b/cmd/root.go index c6247bc..b8d44ae 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -103,27 +103,18 @@ func runInteractiveMode() { } func connectToHost(hostName string) { - // Parse SSH configurations to verify host exists - var hosts []config.SSHHost + // Quick check if host exists without full parsing (optimized for connection) + var hostFound bool var err error if configFile != "" { - hosts, err = config.ParseSSHConfigFile(configFile) + hostFound, err = config.QuickHostExistsInFile(hostName, configFile) } else { - hosts, err = config.ParseSSHConfig() + hostFound, err = config.QuickHostExists(hostName) } if err != nil { - log.Fatalf("Error reading SSH config file: %v", err) - } - - // Check if host exists - var hostFound bool - for _, host := range hosts { - if host.Name == hostName { - hostFound = true - break - } + log.Fatalf("Error checking SSH config: %v", err) } if !hostFound { diff --git a/internal/config/ssh.go b/internal/config/ssh.go index d54d71b..abd1f3d 100644 --- a/internal/config/ssh.go +++ b/internal/config/ssh.go @@ -399,6 +399,11 @@ func processIncludeDirective(pattern string, baseConfigPath string, processedFil continue } + // Skip common non-SSH config file types + if isNonSSHConfigFile(match) { + continue + } + // Recursively parse the included file hosts, err := parseSSHConfigFileWithProcessedFiles(match, processedFiles) if err != nil { @@ -411,6 +416,82 @@ func processIncludeDirective(pattern string, baseConfigPath string, processedFil return allHosts, nil } +// isNonSSHConfigFile checks if a file should be excluded from SSH config parsing +func isNonSSHConfigFile(filePath string) bool { + fileName := strings.ToLower(filepath.Base(filePath)) + + // Skip common documentation files + if fileName == "readme" || fileName == "readme.txt" { + return true + } + + // Skip files with common non-config extensions + excludedExtensions := []string{ + ".txt", ".md", ".rst", ".doc", ".docx", ".pdf", + ".log", ".tmp", ".bak", ".old", ".orig", + ".json", ".xml", ".yaml", ".yml", ".toml", + ".sh", ".bash", ".zsh", ".fish", ".ps1", ".bat", ".cmd", + ".py", ".pl", ".rb", ".js", ".php", ".go", ".c", ".cpp", + ".jpg", ".jpeg", ".png", ".gif", ".bmp", ".svg", + ".zip", ".tar", ".gz", ".bz2", ".xz", + } + + for _, ext := range excludedExtensions { + if strings.HasSuffix(fileName, ext) { + return true + } + } + + // Skip hidden files (starting with .) + if strings.HasPrefix(fileName, ".") { + return true + } + + // Additional check: if file contains common non-SSH content indicators + // This is a more expensive check, so we do it last + if hasNonSSHContent(filePath) { + return true + } + + return false +} + +// hasNonSSHContent performs a quick content check to identify non-SSH files +func hasNonSSHContent(filePath string) bool { + file, err := os.Open(filePath) + if err != nil { + return false // If we can't read it, don't exclude it + } + defer file.Close() + + // Read only the first few KB to check content + buffer := make([]byte, 2048) + n, err := file.Read(buffer) + if err != nil && err != io.EOF { + return false + } + + content := strings.ToLower(string(buffer[:n])) + + // Check for common non-SSH file indicators + nonSSHIndicators := []string{ + "", "", "