Merge branch 'fix-executable-completion-dir-symlinks' of https://github.com/devangpratap/kitty
Some checks are pending
CI / Linux (python=3.14 cc=clang sanitize=1) (push) Waiting to run
CI / Linux (python=3.12 cc=gcc sanitize=0) (push) Waiting to run
CI / Linux (python=3.13 cc=gcc sanitize=1) (push) Waiting to run
CI / Linux package (push) Waiting to run
CI / Bundle test (macos-latest) (push) Waiting to run
CI / Bundle test (ubuntu-latest) (push) Waiting to run
CI / macOS Brew (push) Waiting to run
CI / Test ./dev.sh and benchmark (push) Waiting to run
CodeQL / CodeQL-Build (actions, ubuntu-latest) (push) Waiting to run
CodeQL / CodeQL-Build (c, macos-latest) (push) Waiting to run
CodeQL / CodeQL-Build (c, ubuntu-latest) (push) Waiting to run
CodeQL / CodeQL-Build (go, ubuntu-latest) (push) Waiting to run
CodeQL / CodeQL-Build (python, ubuntu-latest) (push) Waiting to run
Depscan / Scan dependencies for vulnerabilities (push) Waiting to run

This commit is contained in:
Kovid Goyal 2026-09-17 06:35:01 +05:30
commit b079feaf43
No known key found for this signature in database
GPG key ID: 06BC317B515ACE7C
2 changed files with 10 additions and 2 deletions

View file

@ -123,8 +123,13 @@ func CompleteExecutablesInPath(prefix string, paths ...string) []string {
entries, err := os.ReadDir(dir)
if err == nil {
for _, e := range entries {
if strings.HasPrefix(e.Name(), prefix) && !e.IsDir() && unix.Access(filepath.Join(dir, e.Name()), unix.X_OK) == nil {
ans = append(ans, e.Name())
if strings.HasPrefix(e.Name(), prefix) {
// A symlink to a directory has IsDir() false but still passes the X_OK
// check, since directories are executable in the access(2) sense.
p := filepath.Join(dir, e.Name())
if unix.Access(p, unix.X_OK) == nil && !is_dir_or_symlink_to_dir(e, p) {
ans = append(ans, e.Name())
}
}
}
}

View file

@ -155,6 +155,9 @@ func TestCompleteExecutables(t *testing.T) {
create("two", "two-exec", 0700)
os.Symlink(filepath.Join(tdir, "two", "two-exec"), filepath.Join(tdir, "one", "s"))
os.Symlink(filepath.Join(tdir, "one", "one-not-exec"), filepath.Join(tdir, "one", "n"))
// A symlink to a directory passes the X_OK check, so it must not be offered as a command.
os.Mkdir(filepath.Join(tdir, "two", "subdir"), 0700)
os.Symlink(filepath.Join(tdir, "two", "subdir"), filepath.Join(tdir, "one", "d"))
t.Setenv("PATH", strings.Join([]string{filepath.Join(tdir, "one"), filepath.Join(tdir, "two")}, string(os.PathListSeparator)))
test_candidates := func(prefix string, expected ...string) {