package utils import ( "os" "path/filepath" "strings" logger "git.site.quack-lab.dev/dave/cylogger" ) // pathLogger is a scoped logger for the utils/path package. var pathLogger = logger.Default.WithPrefix("utils/path") // ResolvePath resolves a path to an absolute path, handling ~ expansion and cleaning func ResolvePath(path string) string { resolvePathLogger := pathLogger.WithPrefix("ResolvePath").WithField("inputPath", path) resolvePathLogger.Trace("Resolving path: %q", path) // Handle empty path if path == "" { resolvePathLogger.Trace("Empty path, returning empty string") return "" } // Check if path is absolute if filepath.IsAbs(path) { resolvePathLogger.Trace("Path is already absolute: %q", path) cleaned := filepath.ToSlash(filepath.Clean(path)) resolvePathLogger.Trace("Cleaned absolute path: %q", cleaned) return cleaned } // Handle ~ expansion if strings.HasPrefix(path, "~") { homeDir, _ := os.UserHomeDir() if strings.HasPrefix(path, "~/") || strings.HasPrefix(path, "~\\") { path = filepath.Join(homeDir, path[2:]) } else if path == "~" { path = homeDir } else { // ~something (like ~~), treat first ~ as home expansion, rest as literal path = homeDir + path[1:] } resolvePathLogger.Trace("Expanded ~ to home directory: %q", path) } // Make absolute if not already if !filepath.IsAbs(path) { absPath, err := filepath.Abs(path) if err != nil { resolvePathLogger.Error("Failed to get absolute path: %v", err) return filepath.ToSlash(filepath.Clean(path)) } resolvePathLogger.Trace("Made path absolute: %q -> %q", path, absPath) path = absPath } // Clean the path and normalize to forward slashes for consistency cleaned := filepath.ToSlash(filepath.Clean(path)) resolvePathLogger.Trace("Final cleaned path: %q", cleaned) return cleaned } // GetRelativePath returns the relative path from base to target func GetRelativePath(base, target string) (string, error) { getRelativePathLogger := pathLogger.WithPrefix("GetRelativePath") getRelativePathLogger.Debug("Getting relative path from %q to %q", base, target) relPath, err := filepath.Rel(base, target) if err != nil { getRelativePathLogger.Error("Failed to get relative path: %v", err) return "", err } // Use forward slashes for consistency relPath = filepath.ToSlash(relPath) getRelativePathLogger.Debug("Relative path: %q", relPath) return relPath, nil }