diff --git a/src/Project.zig b/src/Project.zig index 9ba122d..12b1d60 100644 --- a/src/Project.zig +++ b/src/Project.zig @@ -2570,7 +2570,6 @@ pub fn request_vcs_content(self: *Self, file_path: []const u8, vcs_id: []const u .file_path = try self.allocator.dupe(u8, file_path), .vcs_id = try self.allocator.dupe(u8, vcs_id), }; - self.logger_git.print("cat-file request {}:{s}:{s}", .{ request, vcs_id, file_path }); git.cat_file(@intFromPtr(request), vcs_id) catch |e| self.logger_git.print_err("cat-file", "failed: {t}", .{e}); } diff --git a/src/buffer/Buffer.zig b/src/buffer/Buffer.zig index 6a2a5de..9bc1fc8 100644 --- a/src/buffer/Buffer.zig +++ b/src/buffer/Buffer.zig @@ -48,7 +48,7 @@ auto_save: bool = false, meta: ?[]const u8 = null, lsp_version: usize = 1, vcs_id: ?[]const u8 = null, -vcs_content: ?[]const u8 = null, +vcs_content: ?ArrayList(u8) = null, undo_head: ?*UndoNode = null, redo_head: ?*UndoNode = null, @@ -1193,7 +1193,7 @@ pub fn create(allocator: Allocator) error{OutOfMemory}!*Self { } pub fn deinit(self: *Self) void { - if (self.vcs_content) |buf| self.external_allocator.free(buf); + self.clear_vcs_content(); if (self.vcs_id) |buf| self.external_allocator.free(buf); if (self.meta) |buf| self.external_allocator.free(buf); if (self.file_buf) |buf| self.external_allocator.free(buf); @@ -1225,6 +1225,42 @@ pub inline fn get_file_path(self: *const Self) []const u8 { return self.file_path_buf.items; } +pub fn set_vcs_id(self: *Self, vcs_id: []const u8) error{OutOfMemory}!bool { + if (self.vcs_id) |old_id| { + if (std.mem.eql(u8, old_id, vcs_id)) return false; + self.external_allocator.free(old_id); + } + self.clear_vcs_content(); + self.vcs_id = try self.external_allocator.dupe(u8, vcs_id); + return true; +} + +pub fn get_vcs_id(self: *Self) ?[]const u8 { + return self.vcs_id; +} + +pub fn set_vcs_content(self: *Self, vcs_id: []const u8, vcs_content: []const u8) error{OutOfMemory}!void { + _ = try self.set_vcs_id(vcs_id); + if (self.vcs_content) |*al| { + try al.appendSlice(self.external_allocator, vcs_content); + } else { + var al: ArrayList(u8) = .empty; + try al.appendSlice(self.external_allocator, vcs_content); + self.vcs_content = al; + } +} + +pub fn clear_vcs_content(self: *Self) void { + if (self.vcs_content) |*buf| { + buf.deinit(self.external_allocator); + self.vcs_content = null; + } +} + +pub fn get_vcs_content(self: *Self) ?[]const u8 { + return if (self.vcs_content) |*buf| buf.items else null; +} + pub fn update_last_used_time(self: *Self) void { self.utime = std.time.milliTimestamp(); } @@ -1638,6 +1674,7 @@ pub fn write_state(self: *const Self, writer: *std.Io.Writer) error{ Stop, OutOf dirty, self.meta, self.file_type_name, + self.vcs_id, content.written(), }); } @@ -1649,6 +1686,7 @@ pub fn extract_state(self: *Self, iter: *[]const u8) !void { var file_type_name: []const u8 = undefined; var dirty: bool = undefined; var meta: ?[]const u8 = null; + var vcs_id: ?[]const u8 = null; var content: []const u8 = undefined; if (!try cbor.matchValue(iter, .{ @@ -1661,6 +1699,7 @@ pub fn extract_state(self: *Self, iter: *[]const u8) !void { cbor.extract(&dirty), cbor.extract(&meta), cbor.extract(&file_type_name), + cbor.extract(&vcs_id), cbor.extract(&content), })) return error.Stop; diff --git a/src/tui/mainview.zig b/src/tui/mainview.zig index f21f4a9..947839a 100644 --- a/src/tui/mainview.zig +++ b/src/tui/mainview.zig @@ -1943,3 +1943,27 @@ pub fn cancel_info_content(self: *Self) tp.result { _ = self.toggle_panel_view(info_view, .disable) catch |e| return tp.exit_error(e, @errorReturnTrace()); tui.need_render(); } + +pub fn vcs_id_update(self: *Self, m: tp.message) void { + var file_path: []const u8 = undefined; + var vcs_id: []const u8 = undefined; + + if (m.match(.{ "PRJ", "vcs_id", tp.extract(&file_path), tp.extract(&vcs_id) }) catch return) { + const buffer = self.buffer_manager.get_buffer_for_file(file_path) orelse return; + const need_vcs_content = buffer.set_vcs_id(vcs_id) catch false; + if (need_vcs_content) + project_manager.request_vcs_content(file_path, vcs_id) catch {}; + } +} + +pub fn vcs_content_update(self: *Self, m: tp.message) void { + var file_path: []const u8 = undefined; + var vcs_id: []const u8 = undefined; + var content: []const u8 = undefined; + + if (m.match(.{ "PRJ", "vcs_content", tp.extract(&file_path), tp.extract(&vcs_id), tp.extract(&content) }) catch return) { + const buffer = self.buffer_manager.get_buffer_for_file(file_path) orelse return; + buffer.set_vcs_content(vcs_id, content) catch {}; + std.log.debug("vcs_content: {d} bytes of {d} id:{s}", .{ content.len, (buffer.get_vcs_content() orelse &.{}).len, vcs_id }); + } +} diff --git a/src/tui/tui.zig b/src/tui/tui.zig index 44a32a7..6a90cb8 100644 --- a/src/tui/tui.zig +++ b/src/tui/tui.zig @@ -527,6 +527,12 @@ fn receive_safe(self: *Self, from: tp.pid_ref, m: tp.message) !void { if (try m.match(.{ "PRJ", "recent_projects", tp.more })) // async recent projects request return self.enter_overlay_mode_with_args(@import("mode/overlay/open_recent_project.zig").Type, .{ .args = m }); + if (try m.match(.{ "PRJ", "vcs_id", tp.more })) + return if (mainview()) |mv| mv.vcs_id_update(m); + + if (try m.match(.{ "PRJ", "vcs_content", tp.more })) + return if (mainview()) |mv| mv.vcs_content_update(m); + if (try m.match(.{ "PRJ", tp.more })) // drop late project manager query responses return;