fix: watch all directories within the project tree
This commit is contained in:
parent
583344d413
commit
348c2055da
3 changed files with 40 additions and 10 deletions
|
|
@ -587,6 +587,10 @@ pub fn query_recent_files(self: *Self, from: tp.pid_ref, max: usize, query_: []c
|
||||||
return @min(max, matches.items.len);
|
return @min(max, matches.items.len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn walk_tree_dir_callback(parent: tp.pid_ref, root_path: []const u8, dir_path: []const u8) error{Exit}!void {
|
||||||
|
try parent.send(.{ "walk_tree_dir", root_path, dir_path });
|
||||||
|
}
|
||||||
|
|
||||||
fn walk_tree_entry_callback(parent: tp.pid_ref, root_path: []const u8, file_path: []const u8, mtime_high: i64, mtime_low: i64) error{Exit}!void {
|
fn walk_tree_entry_callback(parent: tp.pid_ref, root_path: []const u8, file_path: []const u8, mtime_high: i64, mtime_low: i64) error{Exit}!void {
|
||||||
const file_type: []const u8, const file_icon: []const u8, const file_color: u24 = guess_file_type(file_path);
|
const file_type: []const u8, const file_icon: []const u8, const file_color: u24 = guess_file_type(file_path);
|
||||||
try parent.send(.{ "walk_tree_entry", root_path, file_path, mtime_high, mtime_low, file_type, file_icon, file_color });
|
try parent.send(.{ "walk_tree_entry", root_path, file_path, mtime_high, mtime_low, file_type, file_icon, file_color });
|
||||||
|
|
@ -2830,6 +2834,7 @@ fn start_walker(self: *Self) void {
|
||||||
.follow_directory_symlinks = tp.env.get().is("follow_directory_symlinks"),
|
.follow_directory_symlinks = tp.env.get().is("follow_directory_symlinks"),
|
||||||
.maximum_symlink_depth = @intCast(tp.env.get().num("maximum_symlink_depth")),
|
.maximum_symlink_depth = @intCast(tp.env.get().num("maximum_symlink_depth")),
|
||||||
.log_ignored_links = tp.env.get().is("log_ignored_links"),
|
.log_ignored_links = tp.env.get().is("log_ignored_links"),
|
||||||
|
.dir_callback = walk_tree_dir_callback,
|
||||||
}) catch blk: {
|
}) catch blk: {
|
||||||
self.state.walk_tree = .failed;
|
self.state.walk_tree = .failed;
|
||||||
break :blk null;
|
break :blk null;
|
||||||
|
|
|
||||||
|
|
@ -425,6 +425,10 @@ const Process = struct {
|
||||||
|
|
||||||
if (try cbor.match(m.buf, .{ "FW", "change", tp.extract(&path), tp.extract(&event_type) })) {
|
if (try cbor.match(m.buf, .{ "FW", "change", tp.extract(&path), tp.extract(&event_type) })) {
|
||||||
self.handle_file_watch_event(path, event_type);
|
self.handle_file_watch_event(path, event_type);
|
||||||
|
} else if (try cbor.match(m.buf, .{ "walk_tree_dir", tp.extract(&project_directory), tp.extract(&path) })) {
|
||||||
|
var abs_buf: [std.fs.max_path_bytes]u8 = undefined;
|
||||||
|
const abs_path = std.fmt.bufPrint(&abs_buf, "{s}{c}{s}", .{ project_directory, std.fs.path.sep, path }) catch return;
|
||||||
|
file_watcher.watch(abs_path) catch |e| self.logger.err("file_watcher.watch_dir", e);
|
||||||
} else if (try cbor.match(m.buf, .{ "walk_tree_entry", tp.extract(&project_directory), tp.more })) {
|
} else if (try cbor.match(m.buf, .{ "walk_tree_entry", tp.extract(&project_directory), tp.more })) {
|
||||||
if (self.projects.get(project_directory)) |project|
|
if (self.projects.get(project_directory)) |project|
|
||||||
project.walk_tree_entry(m) catch |e| self.logger.err("walk_tree_entry", e);
|
project.walk_tree_entry(m) catch |e| self.logger.err("walk_tree_entry", e);
|
||||||
|
|
@ -440,6 +444,15 @@ const Process = struct {
|
||||||
} else if (try cbor.match(m.buf, .{ "git", tp.extract(&context), "blame", tp.more })) {
|
} else if (try cbor.match(m.buf, .{ "git", tp.extract(&context), "blame", tp.more })) {
|
||||||
const request: *Project.GitBlameRequest = @ptrFromInt(context);
|
const request: *Project.GitBlameRequest = @ptrFromInt(context);
|
||||||
request.project.process_git_response(self.parent.ref(), m) catch |e| self.logger.err("git-blame", e);
|
request.project.process_git_response(self.parent.ref(), m) catch |e| self.logger.err("git-blame", e);
|
||||||
|
} else if (try cbor.match(m.buf, .{ "git", tp.extract(&context), "workspace_files", tp.extract(&path) })) {
|
||||||
|
const project: *Project = @ptrFromInt(context);
|
||||||
|
const dir_path = std.fs.path.dirname(path) orelse "";
|
||||||
|
if (dir_path.len > 0) blk: {
|
||||||
|
var abs_buf: [std.fs.max_path_bytes]u8 = undefined;
|
||||||
|
const abs_path = std.fmt.bufPrint(&abs_buf, "{s}{c}{s}", .{ project.name, std.fs.path.sep, dir_path }) catch break :blk;
|
||||||
|
file_watcher.watch(abs_path) catch |e| self.logger.err("file_watcher.watch_dir", e);
|
||||||
|
}
|
||||||
|
project.process_git(self.parent.ref(), m) catch {};
|
||||||
} else if (try cbor.match(m.buf, .{ "git", tp.extract(&context), tp.more })) {
|
} else if (try cbor.match(m.buf, .{ "git", tp.extract(&context), tp.more })) {
|
||||||
const project: *Project = @ptrFromInt(context);
|
const project: *Project = @ptrFromInt(context);
|
||||||
project.process_git(self.parent.ref(), m) catch {};
|
project.process_git(self.parent.ref(), m) catch {};
|
||||||
|
|
|
||||||
|
|
@ -9,11 +9,13 @@ const OutOfMemoryError = error{OutOfMemory};
|
||||||
|
|
||||||
pub const EntryCallBack = *const fn (parent: tp.pid_ref, root_path: []const u8, path: []const u8, mtime_high: i64, mtime_low: i64) error{Exit}!void;
|
pub const EntryCallBack = *const fn (parent: tp.pid_ref, root_path: []const u8, path: []const u8, mtime_high: i64, mtime_low: i64) error{Exit}!void;
|
||||||
pub const DoneCallBack = *const fn (parent: tp.pid_ref, root_path: []const u8) error{Exit}!void;
|
pub const DoneCallBack = *const fn (parent: tp.pid_ref, root_path: []const u8) error{Exit}!void;
|
||||||
|
pub const DirCallBack = *const fn (parent: tp.pid_ref, root_path: []const u8, path: []const u8) error{Exit}!void;
|
||||||
|
|
||||||
pub const Options = struct {
|
pub const Options = struct {
|
||||||
follow_directory_symlinks: bool = false,
|
follow_directory_symlinks: bool = false,
|
||||||
maximum_symlink_depth: usize = 1,
|
maximum_symlink_depth: usize = 1,
|
||||||
log_ignored_links: bool = false,
|
log_ignored_links: bool = false,
|
||||||
|
dir_callback: ?DirCallBack = null,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn start(a_: std.mem.Allocator, root_path_: []const u8, entry_handler: EntryCallBack, done_handler: DoneCallBack, options: Options) (SpawnError || std.fs.Dir.OpenError)!tp.pid {
|
pub fn start(a_: std.mem.Allocator, root_path_: []const u8, entry_handler: EntryCallBack, done_handler: DoneCallBack, options: Options) (SpawnError || std.fs.Dir.OpenError)!tp.pid {
|
||||||
|
|
@ -78,7 +80,13 @@ pub fn start(a_: std.mem.Allocator, root_path_: []const u8, entry_handler: Entry
|
||||||
}
|
}
|
||||||
|
|
||||||
fn next(self: *tree_walker) !void {
|
fn next(self: *tree_walker) !void {
|
||||||
if (try self.walker.next()) |path| {
|
if (try self.walker.next()) |entry| {
|
||||||
|
if (entry.kind == .dir) {
|
||||||
|
if (self.options.dir_callback) |cb|
|
||||||
|
cb(self.parent.ref(), self.root_path, entry.path) catch {};
|
||||||
|
return tp.self_pid().send(.{"next"});
|
||||||
|
}
|
||||||
|
const path = entry.path;
|
||||||
const stat = self.dir.statFile(path) catch {
|
const stat = self.dir.statFile(path) catch {
|
||||||
try self.entry_handler(self.parent.ref(), self.root_path, path, 0, 0);
|
try self.entry_handler(self.parent.ref(), self.root_path, path, 0, 0);
|
||||||
return tp.self_pid().send(.{"next"});
|
return tp.self_pid().send(.{"next"});
|
||||||
|
|
@ -123,6 +131,8 @@ const FilteredWalker = struct {
|
||||||
name_buffer: std.ArrayListUnmanaged(u8),
|
name_buffer: std.ArrayListUnmanaged(u8),
|
||||||
options: Options,
|
options: Options,
|
||||||
|
|
||||||
|
const Kind = enum { file, dir };
|
||||||
|
const Entry = struct { path: []const u8, kind: Kind };
|
||||||
const Path = []const u8;
|
const Path = []const u8;
|
||||||
|
|
||||||
const StackItem = struct {
|
const StackItem = struct {
|
||||||
|
|
@ -160,7 +170,7 @@ const FilteredWalker = struct {
|
||||||
self.name_buffer.deinit(self.allocator);
|
self.name_buffer.deinit(self.allocator);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn next(self: *FilteredWalker) OutOfMemoryError!?Path {
|
fn next(self: *FilteredWalker) OutOfMemoryError!?Entry {
|
||||||
while (self.stack.items.len != 0) {
|
while (self.stack.items.len != 0) {
|
||||||
var top = &self.stack.items[self.stack.items.len - 1];
|
var top = &self.stack.items[self.stack.items.len - 1];
|
||||||
var containing = top;
|
var containing = top;
|
||||||
|
|
@ -182,17 +192,17 @@ const FilteredWalker = struct {
|
||||||
switch (base.kind) {
|
switch (base.kind) {
|
||||||
.directory => {
|
.directory => {
|
||||||
_ = try self.next_directory(&base, &top, &containing, top.symlink_depth);
|
_ = try self.next_directory(&base, &top, &containing, top.symlink_depth);
|
||||||
continue;
|
return .{ .path = self.name_buffer.items, .kind = .dir };
|
||||||
},
|
},
|
||||||
.file => return self.name_buffer.items,
|
.file => return .{ .path = self.name_buffer.items, .kind = .file },
|
||||||
.sym_link => {
|
.sym_link => {
|
||||||
if (top.symlink_depth == 0) {
|
if (top.symlink_depth == 0) {
|
||||||
if (self.options.log_ignored_links)
|
if (self.options.log_ignored_links)
|
||||||
std.log.warn("TOO MANY LINKS! ignoring symlink: {s}", .{base.name});
|
std.log.warn("TOO MANY LINKS! ignoring symlink: {s}", .{base.name});
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (try self.next_sym_link(&base, &top, &containing, top.symlink_depth -| 1)) |file|
|
if (try self.next_sym_link(&base, &top, &containing, top.symlink_depth -| 1)) |entry|
|
||||||
return file
|
return entry
|
||||||
else
|
else
|
||||||
continue;
|
continue;
|
||||||
},
|
},
|
||||||
|
|
@ -229,15 +239,17 @@ const FilteredWalker = struct {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn next_sym_link(self: *FilteredWalker, base: *const std.fs.Dir.Entry, top: **StackItem, containing: **StackItem, symlink_depth: usize) !?[]const u8 {
|
fn next_sym_link(self: *FilteredWalker, base: *const std.fs.Dir.Entry, top: **StackItem, containing: **StackItem, symlink_depth: usize) !?Entry {
|
||||||
const st = top.*.iter.dir.statFile(base.name) catch return null;
|
const st = top.*.iter.dir.statFile(base.name) catch return null;
|
||||||
switch (st.kind) {
|
switch (st.kind) {
|
||||||
.directory => {
|
.directory => {
|
||||||
if (self.options.follow_directory_symlinks)
|
if (self.options.follow_directory_symlinks) {
|
||||||
_ = try self.next_directory(base, top, containing, symlink_depth);
|
try self.next_directory(base, top, containing, symlink_depth);
|
||||||
|
return .{ .path = self.name_buffer.items, .kind = .dir };
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
.file => return self.name_buffer.items,
|
.file => return .{ .path = self.name_buffer.items, .kind = .file },
|
||||||
.sym_link => {
|
.sym_link => {
|
||||||
if (symlink_depth == 0) {
|
if (symlink_depth == 0) {
|
||||||
if (self.options.log_ignored_links)
|
if (self.options.log_ignored_links)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue