bug: ResolveAbsPath incorrectly expands relative paths starting with ~ (e.g. ~backup)
Describe the bug
ResolveAbsPath in src/pkg/utils/file_utils.go expands any path where strings.HasPrefix(path, "~") is true by replacing ~ with xdg.Home.
This causes relative directory and file names that happen to start with a tilde (such as ~backup, ~temp, ~notes.txt, or Office lock files like ~$document.docx) to be concatenated directly to the home directory string (e.g. /home/userbackup or C:\Users\\\userbackup), rather than being resolved relative to the current working directory.
To Reproduce
- In any directory, create a folder starting with
~:mkdir ~test - Try to launch superfile pointing to that directory:
spf ~test - Superfile fails to open
./~testand falls back to$HOMEbecause it attempts to stat/home/<user>test(orC:\Users\<user>test). - Inside superfile, open the prompt (
:or>) and run:cd ~test - An error is shown:
/home/<user>test: no such file or directory.
Expected behavior
Tilde expansion should only trigger if the argument is exactly "~", starts with "~/", or starts with "~\\" (on Windows). Other paths starting with ~ should be treated as relative paths and resolved against currentDir.
Code Reference
In src/pkg/utils/file_utils.go (lines 206-210):
func ResolveAbsPath(currentDir string, path string) string {
if !filepath.IsAbs(currentDir) {
slog.Warn("currentDir is not absolute", "currentDir", currentDir)
}
if strings.HasPrefix(path, "~") {
// Current: unconditionally replaces '~' anywhere it starts the string
path = strings.Replace(path, "~", xdg.Home, 1)
}
if !filepath.IsAbs(path) {
path = filepath.Join(currentDir, path)
}
return filepath.Clean(path)
}
Proposed fix
func ResolveAbsPath(currentDir string, path string) string {
if !filepath.IsAbs(currentDir) {
slog.Warn("currentDir is not absolute", "currentDir", currentDir)
}
if path == "~" {
path = xdg.Home
} else if strings.HasPrefix(path, "~/") || (runtime.GOOS == "windows" && strings.HasPrefix(path, "~\\")) {
path = filepath.Join(xdg.Home, path[2:])
}
if !filepath.IsAbs(path) {
path = filepath.Join(currentDir, path)
}
return filepath.Clean(path)
}
System information
- OS: All platforms (Linux, macOS, Windows)
- superfile version: v1.6.0 / main (commit
b2af9a6)
Source: yorukot/superfile