From 157df8cb547ba4cf900b1f9eb75df15384985708 Mon Sep 17 00:00:00 2001 From: Gabriel Schneider Date: Tue, 29 Sep 2026 09:45:38 -0300 Subject: A served-tree pane spoils no Grep, and `look .` from a gone directory is ENOENT A pane named `/virtual` gave Grep the root `/`, which swallowed every other pane's directory and ran out of walk before any file: every Grep missed. Grep passes over panes of the served tree. And `.` from a pane whose directory was gone resolved to the served tree's root (/virtual/), or through the jump list to another pane's directory: a dot path is the looking pane's own, and gone it fails, `look: : no such directory`. Co-Authored-By: Claude Opus 5.5 --- src/fs.zig | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'src/fs.zig') diff --git a/src/fs.zig b/src/fs.zig index 352aa0c4..de02e8e8 100644 --- a/src/fs.zig +++ b/src/fs.zig @@ -677,7 +677,9 @@ pub fn resolve(p: ?*pardes.Pardes, word: []const u8, cwd: []const u8, out: *[409 if (std.mem.startsWith(u8, joined, "/virtual/")) return resolveVirtual(p, joined[8..], out); if (resolveOs(joined, out)) |found| return found; if (resolveVirtual(p, joined, out)) |found| return found; - if (resolveVirtual(p, word, out)) |found| return found; + // `.`, `..` and `./x` name the pane's directory, never the served tree: + // with that directory gone they name nothing (`.` would be /virtual/). + if (!dotRelative(word)) if (resolveVirtual(p, word, out)) |found| return found; if (resolveEmbedded(word, cwd, out)) |source| { const path = std.fmt.bufPrint(out, "/virtual/{s}", .{source.path}) catch return null; return .{ .path = path }; @@ -685,6 +687,14 @@ pub fn resolve(p: ?*pardes.Pardes, word: []const u8, cwd: []const u8, out: *[409 return null; } +/// Whether `word` is spelled relative to the directory it is looked from: +/// `.`, `..`, `./x`, `../x`. +pub fn dotRelative(word: []const u8) bool { + const w = std.mem.trimEnd(u8, word, "/"); + return std.mem.eql(u8, w, ".") or std.mem.eql(u8, w, "..") or + std.mem.startsWith(u8, word, "./") or std.mem.startsWith(u8, word, "../"); +} + /// Where a path really is on the host, and whether it is a directory. The /// path may lie in a mount this editor serves, so the turn is given up for /// the syscalls: another thread answers them. -- cgit v1.3