From 28784eaabfbcfec4ed2491facd75a011ba03f936 Mon Sep 17 00:00:00 2001 From: zegervdv Date: Wed, 16 Nov 2022 06:39:26 +0000 Subject: [PATCH 1/6] feat: add different config options for different VCSes BREAKING CHANGE: `file_history_panel.log_options` has an extra level `git` --- doc/diffview_changelog.txt | 48 ++++++++++ lua/diffview/config.lua | 93 ++++++++++++------- .../views/file_history/file_history_panel.lua | 4 +- lua/diffview/vcs/adapter.lua | 1 + lua/diffview/vcs/adapters/git/init.lua | 8 +- 5 files changed, 114 insertions(+), 40 deletions(-) diff --git a/doc/diffview_changelog.txt b/doc/diffview_changelog.txt index b0a3f178..2282870e 100644 --- a/doc/diffview_changelog.txt +++ b/doc/diffview_changelog.txt @@ -5,6 +5,54 @@ CHANGELOG NOTE: This changelog only encompasses breaking changes. + *diffview.changelog-271* + +PR: https://github.com/sindrets/diffview.nvim/pull/271 + +The config for log options has changed. The table is now divided into +sub-tables per VCS type. This allows you to define +different default log options for history for different VCS tools. +To update your config, just move all your log options into the new table keys +`git` : + + Before: ~ +> + require("diffview").setup({ + -- ... + file_history_panel = { + log_options = { + single_file = { + max_count = 512, + follow = true, + }, + multi_file = { + max_count = 128, + -- follow = false -- `follow` only applies to single-file history + }, + }, + }, + }) +< + + After: ~ +> + require("diffview").setup({ + -- ... + file_history_panel = { + git = { + log_options = { + single_file = { + max_count = 512, + follow = true, + }, + multi_file = { + max_count = 128, + -- follow = false -- `follow` only applies to single-file history + }, + }, + }, + }, + }) *diffview.changelog-190* PR: https://github.com/sindrets/diffview.nvim/pull/190 diff --git a/lua/diffview/config.lua b/lua/diffview/config.lua index 1107c31e..370be191 100644 --- a/lua/diffview/config.lua +++ b/lua/diffview/config.lua @@ -77,12 +77,18 @@ M.defaults = { file_history_panel = { ---@type ConfigLogOptions log_options = { - single_file = { - diff_merges = "combined", - }, - multi_file = { - diff_merges = "first-parent", + git = { + single_file = { + diff_merges = "combined", + }, + multi_file = { + diff_merges = "first-parent", + }, }, + hg = { + single_file = {}, + multi_file = {}, + } }, win_config = { position = "bottom", @@ -238,24 +244,27 @@ M._config = M.defaults ---@type LogOptions M.log_option_defaults = { - follow = false, - first_parent = false, - show_pulls = false, - reflog = false, - all = false, - merges = false, - no_merges = false, - reverse = false, - rev_range = nil, - base = nil, - max_count = 256, - L = {}, - diff_merges = nil, - author = nil, - grep = nil, - G = nil, - S = nil, - path_args = {}, + git = { + follow = false, + first_parent = false, + show_pulls = false, + reflog = false, + all = false, + merges = false, + no_merges = false, + reverse = false, + rev_range = nil, + base = nil, + max_count = 256, + L = {}, + diff_merges = nil, + author = nil, + grep = nil, + G = nil, + S = nil, + path_args = {}, + }, + hg = {}, } ---@return DiffviewConfig @@ -269,14 +278,15 @@ end ---@param single_file boolean ---@param t LogOptions +---@param vcs '"git"' | '"hg"' ---@return LogOptions -function M.get_log_options(single_file, t) +function M.get_log_options(single_file, t, vcs) local log_options if single_file then - log_options = M._config.file_history_panel.log_options.single_file + log_options = M._config.file_history_panel.log_options[vcs].single_file else - log_options = M._config.file_history_panel.log_options.multi_file + log_options = M._config.file_history_panel.log_options[vcs].multi_file end if t then @@ -452,6 +462,17 @@ function M.setup(user_config) local user_log_options = utils.tbl_access(user_config, "file_history_panel.log_options") if user_log_options then + local top_options = { + 'single_file', + 'multi_file', + } + for _, name in ipairs(top_options) do + if user_log_options[name] ~= nil then + utils.warn("Global config of 'file_panel.log_options' has been deprecated. See ':h diffview.changelog-271'.") + end + break + end + local option_names = { "max_count", "follow", @@ -508,15 +529,17 @@ function M.setup(user_config) end for _, name in ipairs({ "single_file", "multi_file" }) do - local t = M._config.file_history_panel.log_options - t[name] = vim.tbl_extend( - "force", - M.log_option_defaults, - t[name] - ) - for k, _ in pairs(t[name]) do - if t[name][k] == "" then - t[name][k] = nil + for _, vcs in ipairs({ "git", "hg" }) do + local t = M._config.file_history_panel.log_options[vcs] + t[name] = vim.tbl_extend( + "force", + M.log_option_defaults[vcs], + t[name] + ) + for k, _ in pairs(t[name]) do + if t[name][k] == "" then + t[name][k] = nil + end end end end diff --git a/lua/diffview/scene/views/file_history/file_history_panel.lua b/lua/diffview/scene/views/file_history/file_history_panel.lua index 82acf7e0..c3914e0f 100644 --- a/lua/diffview/scene/views/file_history/file_history_panel.lua +++ b/lua/diffview/scene/views/file_history/file_history_panel.lua @@ -81,12 +81,12 @@ function FileHistoryPanel:init(opt) self.log_options = { single_file = vim.tbl_extend( "force", - conf.file_history_panel.log_options.single_file, + conf.file_history_panel.log_options[self.adapter.config_key].single_file, opt.log_options ), multi_file = vim.tbl_extend( "force", - conf.file_history_panel.log_options.multi_file, + conf.file_history_panel.log_options[self.adapter.config_key].multi_file, opt.log_options ), } diff --git a/lua/diffview/vcs/adapter.lua b/lua/diffview/vcs/adapter.lua index 6a1cea29..1511951b 100644 --- a/lua/diffview/vcs/adapter.lua +++ b/lua/diffview/vcs/adapter.lua @@ -41,6 +41,7 @@ local M = {} local VCSAdapter = oop.create_class("VCSAdapter") VCSAdapter.Rev = Rev +VCSAdapter.config_key = nil ---@class vcs.adapter.VCSAdapter.Opt ---@field cpath string? # CWD path diff --git a/lua/diffview/vcs/adapters/git/init.lua b/lua/diffview/vcs/adapters/git/init.lua index 189382ca..87891a12 100644 --- a/lua/diffview/vcs/adapters/git/init.lua +++ b/lua/diffview/vcs/adapters/git/init.lua @@ -27,6 +27,7 @@ local M = {} local GitAdapter = oop.create_class("GitAdapter", VCSAdapter) GitAdapter.Rev = GitRev +GitAdapter.config_key = "git" ---@return string, string function M.pathspec_split(pathspec) @@ -580,7 +581,7 @@ end ---@return boolean ok, string description function GitAdapter:file_history_dry_run(log_opt) local single_file = self:is_single_file(log_opt.path_args, log_opt.L) - local log_options = config.get_log_options(single_file, log_opt) + local log_options = config.get_log_options(single_file, log_opt, "git") local options = vim.tbl_map(function(v) return vim.fn.shellescape(v) @@ -675,7 +676,7 @@ function GitAdapter:file_history_options(range, paths, args) for _, names in ipairs(log_flag_names) do local key, _ = names[1]:gsub("%-", "_") local v = argo:get_flag(names, { - expect_string = type(config.log_option_defaults[key]) ~= "boolean", + expect_string = type(config.log_option_defaults[self.config_key][key]) ~= "boolean", expect_list = names[1] == "L", }) log_options[key] = v @@ -926,7 +927,8 @@ function GitAdapter:file_history_worker(thread, log_opt, opt, co_state, callback ---@type LogOptions local log_options = config.get_log_options( single_file, - single_file and log_opt.single_file or log_opt.multi_file + single_file and log_opt.single_file or log_opt.multi_file, + "git" ) local is_trace = #log_options.L > 0 From 49955eef7f7589eb6a1f6c4f9204407f635e7686 Mon Sep 17 00:00:00 2001 From: zegervdv Date: Sun, 13 Nov 2022 17:59:30 +0000 Subject: [PATCH 2/6] refactor: process object name and file path in the adapter --- lua/diffview/vcs/adapter.lua | 5 +++-- lua/diffview/vcs/adapters/git/init.lua | 5 ++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lua/diffview/vcs/adapter.lua b/lua/diffview/vcs/adapter.lua index 1511951b..b2954f40 100644 --- a/lua/diffview/vcs/adapter.lua +++ b/lua/diffview/vcs/adapter.lua @@ -166,9 +166,10 @@ end ---@diagnostic disable: unused-local, missing-return ----@param args string[] +---@param path string +---@param rev Rev? ---@return string[]? args to show commit content -function VCSAdapter:get_show_args(args) +function VCSAdapter:get_show_args(path, rev) oop.abstract_stub() end diff --git a/lua/diffview/vcs/adapters/git/init.lua b/lua/diffview/vcs/adapters/git/init.lua index 87891a12..d5612b51 100644 --- a/lua/diffview/vcs/adapters/git/init.lua +++ b/lua/diffview/vcs/adapters/git/init.lua @@ -223,9 +223,8 @@ function GitAdapter:get_command() return config.get_config().git_cmd end ----@param args table -function GitAdapter:get_show_args(args) - return utils.vec_join(self:args(), "show", args) +function GitAdapter:get_show_args(path, rev) + return utils.vec_join(self:args(), "show", { ("%s:%s"):format(rev:object_name() or "", path) }) end function GitAdapter:get_dir(path) From ccb406af3067db4bc6ab4ba7b05835caf7ff113a Mon Sep 17 00:00:00 2001 From: zegervdv Date: Wed, 16 Nov 2022 17:48:53 +0000 Subject: [PATCH 3/6] refactor:make time offset parsing VCS type specific --- lua/diffview/vcs/adapters/git/commit.lua | 9 +++++++++ lua/diffview/vcs/commit.lua | 8 -------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/lua/diffview/vcs/adapters/git/commit.lua b/lua/diffview/vcs/adapters/git/commit.lua index aec560f7..35086afb 100644 --- a/lua/diffview/vcs/adapters/git/commit.lua +++ b/lua/diffview/vcs/adapters/git/commit.lua @@ -22,6 +22,15 @@ local GitCommit = oop.create_class("GitCommit", Commit.__get()) function GitCommit:init(opt) GitCommit:super().init(self, opt) + + if opt.time_offset then + self.time_offset = Commit.parse_time_offset(opt.time_offset) + self.time = self.time - self.time_offset + else + self.time_offset = 0 + end + + self.iso_date = Commit.time_to_iso(self.time, self.time_offset) end ---@param rev_arg string diff --git a/lua/diffview/vcs/commit.lua b/lua/diffview/vcs/commit.lua index 59b08f1e..28901b16 100644 --- a/lua/diffview/vcs/commit.lua +++ b/lua/diffview/vcs/commit.lua @@ -27,14 +27,6 @@ function Commit:init(opt) self.subject = opt.subject self.body = opt.body - if opt.time_offset then - self.time_offset = Commit.parse_time_offset(opt.time_offset) - self.time = self.time - self.time_offset - else - self.time_offset = 0 - end - - self.iso_date = Commit.time_to_iso(self.time, self.time_offset) end ---@diagnostic disable: unused-local, missing-return From d0bfe3b3c2f934badbca71b1c869c06d42cf725f Mon Sep 17 00:00:00 2001 From: zegervdv Date: Fri, 25 Nov 2022 06:44:28 +0000 Subject: [PATCH 4/6] refactor: move tracked and untracked file listing to adapter --- lua/diffview/config.lua | 4 + lua/diffview/vcs/adapter.lua | 43 +++--- lua/diffview/vcs/adapters/git/init.lua | 175 +++++++++++++++++++++-- lua/diffview/vcs/file.lua | 2 +- lua/diffview/vcs/utils.lua | 183 +------------------------ 5 files changed, 194 insertions(+), 213 deletions(-) diff --git a/lua/diffview/config.lua b/lua/diffview/config.lua index 370be191..5237f1f6 100644 --- a/lua/diffview/config.lua +++ b/lua/diffview/config.lua @@ -492,6 +492,10 @@ function M.setup(user_config) end end + if type(M._config.file_history_panel.log_options.git) == "nil" then + utils.warn("Global config of 'file_panel.log_options' has been deprecated. See ':h diffview.changelog-XXX'.") + end + --#endregion if #M._config.git_cmd == 0 then diff --git a/lua/diffview/vcs/adapter.lua b/lua/diffview/vcs/adapter.lua index b2954f40..a9d34578 100644 --- a/lua/diffview/vcs/adapter.lua +++ b/lua/diffview/vcs/adapter.lua @@ -228,27 +228,6 @@ function VCSAdapter:rev_to_args(left, right) oop.abstract_stub() end ----Arguments to show name and status of files ----@param args string[]? Extra args ----@return string[] -function VCSAdapter:get_namestat_args(args) - oop.abstract_stub() -end - ----Arguments to show number of changes to files ----@param args string[]? Extra args ----@return string[] -function VCSAdapter:get_numstat_args(args) - oop.abstract_stub() -end - ----Arguments to list all files ----@param args string[]? Extra args ----@return string[] -function VCSAdapter:get_files_args(args) - oop.abstract_stub() -end - ---Restore a file to the requested state ---@param path string # file to restore ---@param kind '"staged"'|'"working"' @@ -301,6 +280,26 @@ function VCSAdapter:stage_index_file(file) oop.abstract_stub() end +---@param self VCSAdapter +---@param left Rev +---@param right Rev +---@param args string[] +---@param kind git.FileKind +---@param opt vcs.adapter.LayoutOpt +---@param callback function +VCSAdapter.tracked_files = async.wrap(function(self, left, right, args, kind, opt, callback) + oop.abstract_stub() +end, 7) + +---@param self VCSAdapter +---@param left Rev +---@param right Rev +---@param opt vcs.adapter.LayoutOpt +---@param callback function +VCSAdapter.untracked_files = async.wrap(function(self, left, right, opt, callback) + oop.abstract_stub() +end, 5) + ---@diagnostic enable: unused-local, missing-return ---@param self VCSAdapter @@ -309,7 +308,7 @@ end VCSAdapter.show = async.wrap(function(self, args, callback) local job = Job:new({ command = self:bin(), - args = self:get_show_args(args), + args = self:get_show_args(args.path, args.rev), cwd = self.ctx.toplevel, ---@type Job on_exit = async.void(function(j) diff --git a/lua/diffview/vcs/adapters/git/init.lua b/lua/diffview/vcs/adapters/git/init.lua index d5612b51..54ad7688 100644 --- a/lua/diffview/vcs/adapters/git/init.lua +++ b/lua/diffview/vcs/adapters/git/init.lua @@ -16,6 +16,7 @@ local lazy = require("diffview.lazy") local logger = require("diffview.logger") local oop = require("diffview.oop") local utils = require("diffview.utils") +local vcs_utils = require("diffview.vcs.utils") ---@type PathLib local pl = lazy.access(utils, "path") @@ -1242,17 +1243,6 @@ function GitAdapter:rev_to_args(left, right) end end -function GitAdapter:get_namestat_args(args) - return utils.vec_join(self:args(), "diff", "--ignore-submodules", "--name-status", args) -end - -function GitAdapter:get_numstat_args(args) - return utils.vec_join(self:args(), "diff", "--ignore-submodules", "--numstat", args) -end - -function GitAdapter:get_files_args(args) - return utils.vec_join(self:args(), "ls-files", "--others", "--exclude-standard", args) -end ---@param path string ---@param kind vcs.FileKind @@ -1404,6 +1394,169 @@ function GitAdapter:show_untracked() return vim.trim(out[1] or "") ~= "no" end +GitAdapter.tracked_files = async.wrap(function (self, left, right, args, kind, opt, callback) + ---@type FileEntry[] + local files = {} + ---@type FileEntry[] + local conflicts = {} + ---@type CountDownLatch + local latch = CountDownLatch(2) + local debug_opt = { + context = "GitAdapter>tracked_files()", + func = "s_debug", + debug_level = 1, + no_stdout = true, + } + + ---@param job Job + local function on_exit(job) + utils.handle_job(job, { debug_opt = debug_opt }) + latch:count_down() + end + + local namestat_job = Job:new({ + command = self:bin(), + args = utils.vec_join(self:args(), "diff", "--ignore-submodules", "--name-status", args), + cwd = self.ctx.toplevel, + on_exit = on_exit, + }) + local numstat_job = Job:new({ + command = self:bin(), + args = utils.vec_join(self:args(), "diff", "--ignore-submodules", "--numstat", args), + cwd = self.ctx.toplevel, + on_exit = on_exit, + }) + + namestat_job:start() + numstat_job:start() + latch:await() + local out_status + if not (#namestat_job:result() == #numstat_job:result()) then + out_status = vcs_utils.ensure_output(2, { namestat_job, numstat_job }, "GitAdapter>tracked_files()") + end + + if out_status == JobStatus.ERROR or not (namestat_job.code == 0 and numstat_job.code == 0) then + callback(utils.vec_join(namestat_job:stderr_result(), numstat_job:stderr_result()), nil) + return + end + + local numstat_out = numstat_job:result() + local namestat_out = namestat_job:result() + + local data = {} + local conflict_map = {} + + for i, s in ipairs(namestat_out) do + local status = s:sub(1, 1):gsub("%s", " ") + local name = s:match("[%a%s][^%s]*\t(.*)") + local oldname + + if name:match("\t") ~= nil then + oldname = name:match("(.*)\t") + name = name:gsub("^.*\t", "") + end + + local stats = { + additions = tonumber(numstat_out[i]:match("^%d+")), + deletions = tonumber(numstat_out[i]:match("^%d+%s+(%d+)")), + } + + if not stats.additions or not stats.deletions then + stats = nil + end + + if not (status == "U" and kind == "staged") then + table.insert(data, { + status = status, + name = name, + oldname = oldname, + stats = stats, + }) + end + + if status == "U" then + conflict_map[name] = data[#data] + end + end + + if kind == "working" and next(conflict_map) then + print('') + data = vim.tbl_filter(function(v) + return not conflict_map[v.name] + end, data) + + for _, v in pairs(conflict_map) do + table.insert(conflicts, FileEntry.with_layout(opt.merge_layout, { + adapter = self, + path = v.name, + oldpath = v.oldname, + status = "U", + kind = "conflicting", + rev_ours = self.Rev(RevType.STAGE, 2), + rev_main = self.Rev(RevType.LOCAL), + rev_theirs = self.Rev(RevType.STAGE, 3), + rev_base = self.Rev(RevType.STAGE, 1), + })) + end + end + + for _, v in ipairs(data) do + table.insert(files, FileEntry.with_layout(opt.default_layout, { + adapter = self, + path = v.name, + oldpath = v.oldname, + status = v.status, + stats = v.stats, + kind = kind, + revs = { + a = left, + b = right, + } + })) + end + + callback(nil, files, conflicts) +end, 7) + +GitAdapter.untracked_files = async.wrap(function(self, left, right, opt, callback) + Job:new({ + command = self:bin(), + args = utils.vec_join(self:args(), "ls-files", "--others", "--exclude-standard"), + cwd = self.ctx.toplevel, + ---@type Job + on_exit = function(j) + utils.handle_job(j, { + debug_opt = { + context = "GitAdapter>untracked_files()", + func = "s_debug", + debug_level = 1, + no_stdout = true, + } + }) + + if j.code ~= 0 then + callback(j:stderr_result() or {}, nil) + return + end + + local files = {} + for _, s in ipairs(j:result()) do + table.insert(files, FileEntry.with_layout(opt.default_layout, { + adapter = self, + path = s, + status = "?", + kind = "working", + revs = { + a = left, + b = right, + } + })) + end + callback(nil, files) + end + }):start() +end, 5) + ---Convert revs to string representation. ---@param left Rev ---@param right Rev diff --git a/lua/diffview/vcs/file.lua b/lua/diffview/vcs/file.lua index 1fb00834..194d1253 100644 --- a/lua/diffview/vcs/file.lua +++ b/lua/diffview/vcs/file.lua @@ -142,7 +142,7 @@ function File:_produce_data(callback) end, nil) else self.adapter:show( - { ("%s:%s"):format(self.rev:object_name() or "", self.path) }, + { path = self.path, rev = self.rev }, function(err, result) if err then utils.err( diff --git a/lua/diffview/vcs/utils.lua b/lua/diffview/vcs/utils.lua index 7fa12e17..dfc47107 100644 --- a/lua/diffview/vcs/utils.lua +++ b/lua/diffview/vcs/utils.lua @@ -111,180 +111,6 @@ M.ensure_output = async.wrap(function(max_retries, jobs, log_context, callback) callback(JobStatus.ERROR) end, 4) ----@param adapter VCSAdapter ----@param left Rev ----@param right Rev ----@param args string[] ----@param kind vcs.FileKind ----@param opt vcs.adapter.LayoutOpt ----@param callback function -local tracked_files = async.wrap(function(adapter, left, right, args, kind, opt, callback) - ---@type FileEntry[] - local files = {} - ---@type FileEntry[] - local conflicts = {} - ---@type CountDownLatch - local latch = CountDownLatch(2) - local debug_opt = { - context = "git.utils>tracked_files()", - func = "s_debug", - debug_level = 1, - no_stdout = true, - } - - ---@param job Job - local function on_exit(job) - utils.handle_job(job, { debug_opt = debug_opt }) - latch:count_down() - end - - local namestat_job = Job:new({ - command = adapter:bin(), - args = adapter:get_namestat_args(args), - cwd = adapter.ctx.toplevel, - on_exit = on_exit - }) - local numstat_job = Job:new({ - command = adapter:bin(), - args = adapter:get_numstat_args(args), - cwd = adapter.ctx.toplevel, - on_exit = on_exit - }) - - namestat_job:start() - numstat_job:start() - latch:await() - local out_status - if not (#namestat_job:result() == #numstat_job:result()) then - out_status = M.ensure_output(2, { namestat_job, numstat_job }, "git.utils>tracked_files()") - end - - if out_status == JobStatus.ERROR or not (namestat_job.code == 0 and numstat_job.code == 0) then - callback(utils.vec_join(namestat_job:stderr_result(), numstat_job:stderr_result()), nil) - return - end - - local numstat_out = numstat_job:result() - local data = {} - local conflict_map = {} - - for i, s in ipairs(namestat_job:result()) do - local status = s:sub(1, 1):gsub("%s", " ") - local name = s:match("[%a%s][^%s]*\t(.*)") - local oldname - - if name:match("\t") ~= nil then - oldname = name:match("(.*)\t") - name = name:gsub("^.*\t", "") - end - - local stats = { - additions = tonumber(numstat_out[i]:match("^%d+")), - deletions = tonumber(numstat_out[i]:match("^%d+%s+(%d+)")), - } - - if not stats.additions or not stats.deletions then - stats = nil - end - - if not (status == "U" and kind == "staged") then - table.insert(data, { - status = status, - name = name, - oldname = oldname, - stats = stats, - }) - end - - if status == "U" then - conflict_map[name] = data[#data] - end - end - - if kind == "working" and next(conflict_map) then - data = vim.tbl_filter(function(v) - return not conflict_map[v.name] - end, data) - - for _, v in pairs(conflict_map) do - table.insert(conflicts, FileEntry.with_layout(opt.merge_layout, { - adapter = adapter, - path = v.name, - oldpath = v.oldname, - status = "U", - kind = "conflicting", - revs = { - a = adapter.Rev(RevType.STAGE, 2), -- ours - b = adapter.Rev(RevType.LOCAL), -- local - c = adapter.Rev(RevType.STAGE, 3), -- theirs - d = adapter.Rev(RevType.STAGE, 1), -- base - }, - })) - end - end - - for _, v in ipairs(data) do - table.insert(files, FileEntry.with_layout(opt.default_layout, { - adapter = adapter, - path = v.name, - oldpath = v.oldname, - status = v.status, - stats = v.stats, - kind = kind, - revs = { - a = left, - b = right, - }, - })) - end - - callback(nil, files, conflicts) -end, 7) - ----@param adapter VCSAdapter ----@param left Rev ----@param right Rev ----@param opt vcs.adapter.LayoutOpt ----@param callback function -local untracked_files = async.wrap(function(adapter, left, right, opt, callback) - Job:new({ - command = adapter:bin(), - args = adapter:get_files_args(), - cwd = adapter.ctx.toplevel, - ---@type Job - on_exit = function(j) - utils.handle_job(j, { - debug_opt = { - context = "git.utils>untracked_files()", - func = "s_debug", - debug_level = 1, - no_stdout = true, - } - }) - - if j.code ~= 0 then - callback(j:stderr_result() or {}, nil) - return - end - - local files = {} - for _, s in ipairs(j:result()) do - table.insert(files, FileEntry.with_layout(opt.default_layout, { - adapter = adapter, - path = s, - status = "?", - kind = "working", - revs = { - a = left, - b = right, - }, - })) - end - callback(nil, files) - end - }):start() -end, 5) - ---Get a list of files modified between two revs. ---@param adapter VCSAdapter ---@param left Rev @@ -303,8 +129,7 @@ M.diff_file_list = async.wrap(function(adapter, left, right, path_args, dv_opt, local rev_args = adapter:rev_to_args(left, right) local errors = {} - tracked_files( - adapter, + adapter:tracked_files( left, right, utils.vec_join( @@ -336,7 +161,8 @@ M.diff_file_list = async.wrap(function(adapter, left, right, path_args, dv_opt, end ---@diagnostic disable-next-line: redefined-local - local err, ufiles = untracked_files(adapter, left, right, opt) + local err, ufiles = adapter:untracked_files(left, right, opt) + print('untracked: ', #ufiles) if err then errors[#errors+1] = err utils.err("Failed to get git status for untracked files!", true) @@ -357,8 +183,7 @@ M.diff_file_list = async.wrap(function(adapter, left, right, path_args, dv_opt, else local left_rev = adapter:head_rev() or adapter.Rev.new_null_tree() local right_rev = adapter.Rev(RevType.STAGE, 0) - tracked_files( - adapter, + adapter:tracked_files( left_rev, right_rev, utils.vec_join( From c42d41958356fb05c6ea128ac225f7d760b42c01 Mon Sep 17 00:00:00 2001 From: zegervdv Date: Thu, 15 Dec 2022 17:33:44 +0100 Subject: [PATCH 5/6] fix: cannot call api functions from callback --- lua/diffview/vcs/file.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lua/diffview/vcs/file.lua b/lua/diffview/vcs/file.lua index 194d1253..d1db636b 100644 --- a/lua/diffview/vcs/file.lua +++ b/lua/diffview/vcs/file.lua @@ -146,7 +146,7 @@ function File:_produce_data(callback) function(err, result) if err then utils.err( - ("Failed to create diff buffer: '%s'"):format(api.nvim_buf_get_name(self.bufnr)), + ("Failed to create diff buffer: '%s'"):format(self.path), true ) return From df9db702443d5d0f7b36da2e1d1e6c693abbd624 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sindre=20T=2E=20Str=C3=B8m?= Date: Fri, 16 Dec 2022 17:51:11 +0100 Subject: [PATCH 6/6] Misc adjustments and fixes --- README.md | 14 +++++++---- doc/diffview_changelog.txt | 17 +++++++------- doc/diffview_defaults.txt | 14 +++++++---- lua/diffview/config.lua | 28 +++++++++++----------- lua/diffview/vcs/adapter.lua | 13 ++++++----- lua/diffview/vcs/adapters/git/init.lua | 32 ++++++++++++++------------ lua/diffview/vcs/file.lua | 12 ++++++---- lua/diffview/vcs/utils.lua | 1 - 8 files changed, 74 insertions(+), 57 deletions(-) diff --git a/README.md b/README.md index 8e7a40ad..bd7358dd 100644 --- a/README.md +++ b/README.md @@ -212,11 +212,17 @@ require("diffview").setup({ }, file_history_panel = { log_options = { -- See ':h diffview-config-log_options' - single_file = { - diff_merges = "combined", + git = { + single_file = { + diff_merges = "combined", + }, + multi_file = { + diff_merges = "first-parent", + }, }, - multi_file = { - diff_merges = "first-parent", + hg = { + single_file = {}, + multi_file = {}, }, }, win_config = { -- See ':h diffview-config-win_config' diff --git a/doc/diffview_changelog.txt b/doc/diffview_changelog.txt index 2282870e..660b618b 100644 --- a/doc/diffview_changelog.txt +++ b/doc/diffview_changelog.txt @@ -9,11 +9,11 @@ NOTE: This changelog only encompasses breaking changes. PR: https://github.com/sindrets/diffview.nvim/pull/271 -The config for log options has changed. The table is now divided into -sub-tables per VCS type. This allows you to define -different default log options for history for different VCS tools. -To update your config, just move all your log options into the new table keys -`git` : +The config for log options has changed. In preparation of adding support of +other VCS, the table is now divided into sub-tables per VCS type. This allows +you to define different default log options for different VCS tools. To update +your config, just move all your current log options into the new table key +`git`: Before: ~ > @@ -27,7 +27,6 @@ To update your config, just move all your log options into the new table keys }, multi_file = { max_count = 128, - -- follow = false -- `follow` only applies to single-file history }, }, }, @@ -39,20 +38,20 @@ To update your config, just move all your log options into the new table keys require("diffview").setup({ -- ... file_history_panel = { - git = { - log_options = { + log_options = { + git = { single_file = { max_count = 512, follow = true, }, multi_file = { max_count = 128, - -- follow = false -- `follow` only applies to single-file history }, }, }, }, }) +< *diffview.changelog-190* PR: https://github.com/sindrets/diffview.nvim/pull/190 diff --git a/doc/diffview_defaults.txt b/doc/diffview_defaults.txt index 4bc92c2d..5d34a046 100644 --- a/doc/diffview_defaults.txt +++ b/doc/diffview_defaults.txt @@ -60,11 +60,17 @@ require("diffview").setup({ }, file_history_panel = { log_options = { -- See |diffview-config-log_options| - single_file = { - diff_merges = "combined", + git = { + single_file = { + diff_merges = "combined", + }, + multi_file = { + diff_merges = "first-parent", + }, }, - multi_file = { - diff_merges = "first-parent", + hg = { + single_file = {}, + multi_file = {}, }, }, win_config = { -- See |diffview-config-win_config| diff --git a/lua/diffview/config.lua b/lua/diffview/config.lua index 5237f1f6..ae6c5d36 100644 --- a/lua/diffview/config.lua +++ b/lua/diffview/config.lua @@ -75,8 +75,8 @@ M.defaults = { }, }, file_history_panel = { - ---@type ConfigLogOptions log_options = { + ---@type ConfigLogOptions git = { single_file = { diff_merges = "combined", @@ -85,10 +85,11 @@ M.defaults = { diff_merges = "first-parent", }, }, + ---@type ConfigLogOptions hg = { single_file = {}, multi_file = {}, - } + }, }, win_config = { position = "bottom", @@ -222,7 +223,7 @@ M.defaults = { M.user_emitter = EventEmitter() M._config = M.defaults ----@class LogOptions +---@class GitLogOptions ---@field follow boolean ---@field first_parent boolean ---@field show_pulls boolean @@ -242,8 +243,12 @@ M._config = M.defaults ---@field base string ---@field path_args string[] ----@type LogOptions +---@class HgLogOptions + +---@alias LogOptions GitLogOptions|HgLogOptions + M.log_option_defaults = { + ---@type GitLogOptions git = { follow = false, first_parent = false, @@ -264,6 +269,7 @@ M.log_option_defaults = { S = nil, path_args = {}, }, + ---@type HgLogOptions hg = {}, } @@ -277,9 +283,9 @@ function M.get_config() end ---@param single_file boolean ----@param t LogOptions ----@param vcs '"git"' | '"hg"' ----@return LogOptions +---@param t GitLogOptions|HgLogOptions +---@param vcs "git"|"hg" +---@return GitLogOptions|HgLogOptions function M.get_log_options(single_file, t, vcs) local log_options @@ -463,8 +469,8 @@ function M.setup(user_config) local user_log_options = utils.tbl_access(user_config, "file_history_panel.log_options") if user_log_options then local top_options = { - 'single_file', - 'multi_file', + "single_file", + "multi_file", } for _, name in ipairs(top_options) do if user_log_options[name] ~= nil then @@ -492,10 +498,6 @@ function M.setup(user_config) end end - if type(M._config.file_history_panel.log_options.git) == "nil" then - utils.warn("Global config of 'file_panel.log_options' has been deprecated. See ':h diffview.changelog-XXX'.") - end - --#endregion if #M._config.git_cmd == 0 then diff --git a/lua/diffview/vcs/adapter.lua b/lua/diffview/vcs/adapter.lua index a9d34578..8cc36528 100644 --- a/lua/diffview/vcs/adapter.lua +++ b/lua/diffview/vcs/adapter.lua @@ -168,7 +168,7 @@ end ---@param path string ---@param rev Rev? ----@return string[]? args to show commit content +---@return string[] args to show commit content function VCSAdapter:get_show_args(path, rev) oop.abstract_stub() end @@ -284,7 +284,7 @@ end ---@param left Rev ---@param right Rev ---@param args string[] ----@param kind git.FileKind +---@param kind vcs.FileKind ---@param opt vcs.adapter.LayoutOpt ---@param callback function VCSAdapter.tracked_files = async.wrap(function(self, left, right, args, kind, opt, callback) @@ -303,12 +303,13 @@ end, 5) ---@diagnostic enable: unused-local, missing-return ---@param self VCSAdapter ----@param args string[] +---@param path string +---@param rev? Rev ---@param callback fun(stderr: string[]?, stdout: string[]?) -VCSAdapter.show = async.wrap(function(self, args, callback) +VCSAdapter.show = async.wrap(function(self, path, rev, callback) local job = Job:new({ command = self:bin(), - args = self:get_show_args(args.path, args.rev), + args = self:get_show_args(path, rev), cwd = self.ctx.toplevel, ---@type Job on_exit = async.void(function(j) @@ -343,7 +344,7 @@ VCSAdapter.show = async.wrap(function(self, args, callback) -- silently. -- Solution: queue them and run them one after another. vcs_utils.queue_sync_job(job) -end, 3) +end, 4) ---Convert revs to string representation. ---@param left Rev diff --git a/lua/diffview/vcs/adapters/git/init.lua b/lua/diffview/vcs/adapters/git/init.lua index 54ad7688..fa7bcc46 100644 --- a/lua/diffview/vcs/adapters/git/init.lua +++ b/lua/diffview/vcs/adapters/git/init.lua @@ -224,8 +224,10 @@ function GitAdapter:get_command() return config.get_config().git_cmd end +---@param path string +---@param rev Rev? function GitAdapter:get_show_args(path, rev) - return utils.vec_join(self:args(), "show", { ("%s:%s"):format(rev:object_name() or "", path) }) + return utils.vec_join(self:args(), "show", ("%s:%s"):format(rev and rev:object_name() or "", path)) end function GitAdapter:get_dir(path) @@ -255,7 +257,7 @@ end ---@field flags string[] ---@param adapter GitAdapter ----@param log_options LogOptions +---@param log_options GitLogOptions ---@param single_file boolean ---@return GitAdapter.PreparedLogOpts local function prepare_fh_options(adapter, log_options, single_file) @@ -577,11 +579,11 @@ function GitAdapter:is_single_file(path_args, lflags) return true end ----@param log_opt LogOptions +---@param log_opt GitLogOptions ---@return boolean ok, string description function GitAdapter:file_history_dry_run(log_opt) local single_file = self:is_single_file(log_opt.path_args, log_opt.L) - local log_options = config.get_log_options(single_file, log_opt, "git") + local log_options = config.get_log_options(single_file, log_opt, "git") --[[@as GitLogOptions ]] local options = vim.tbl_map(function(v) return vim.fn.shellescape(v) @@ -593,7 +595,7 @@ function GitAdapter:file_history_dry_run(log_opt) ("Flags: %s"):format(table.concat(options, " ")) ) - log_options = utils.tbl_clone(log_options) --[[@as LogOptions ]] + log_options = utils.tbl_clone(log_options) --[[@as GitLogOptions ]] log_options.max_count = 1 options = prepare_fh_options(self, log_options, single_file).flags @@ -671,8 +673,7 @@ function GitAdapter:file_history_options(range, paths, args) { "S" }, } - ---@type LogOptions - local log_options = { rev_range = range_arg } + local log_options = { rev_range = range_arg } --[[@as GitLogOptions ]] for _, names in ipairs(log_flag_names) do local key, _ = names[1]:gsub("%-", "_") local v = argo:get_flag(names, { @@ -768,7 +769,7 @@ end ---@field thread thread ---@field adapter GitAdapter ---@field path_args string[] ----@field log_options LogOptions +---@field log_options GitLogOptions ---@field prepared_log_opts GitAdapter.PreparedLogOpts ---@field opt vcs.adapter.FileHistoryWorkerSpec ---@field single_file boolean @@ -924,7 +925,7 @@ function GitAdapter:file_history_worker(thread, log_opt, opt, co_state, callback local single_file = self:is_single_file(log_opt.single_file.path_args, log_opt.single_file.L) - ---@type LogOptions + ---@type GitLogOptions local log_options = config.get_log_options( single_file, single_file and log_opt.single_file or log_opt.multi_file, @@ -1394,7 +1395,7 @@ function GitAdapter:show_untracked() return vim.trim(out[1] or "") ~= "no" end -GitAdapter.tracked_files = async.wrap(function (self, left, right, args, kind, opt, callback) +GitAdapter.tracked_files = async.wrap(function(self, left, right, args, kind, opt, callback) ---@type FileEntry[] local files = {} ---@type FileEntry[] @@ -1480,7 +1481,6 @@ GitAdapter.tracked_files = async.wrap(function (self, left, right, args, kind, o end if kind == "working" and next(conflict_map) then - print('') data = vim.tbl_filter(function(v) return not conflict_map[v.name] end, data) @@ -1492,10 +1492,12 @@ GitAdapter.tracked_files = async.wrap(function (self, left, right, args, kind, o oldpath = v.oldname, status = "U", kind = "conflicting", - rev_ours = self.Rev(RevType.STAGE, 2), - rev_main = self.Rev(RevType.LOCAL), - rev_theirs = self.Rev(RevType.STAGE, 3), - rev_base = self.Rev(RevType.STAGE, 1), + revs = { + a = self.Rev(RevType.STAGE, 2), -- ours + b = self.Rev(RevType.LOCAL), -- local + c = self.Rev(RevType.STAGE, 3), -- theirs + d = self.Rev(RevType.STAGE, 1), -- base + }, })) end end diff --git a/lua/diffview/vcs/file.lua b/lua/diffview/vcs/file.lua index d1db636b..10afb996 100644 --- a/lua/diffview/vcs/file.lua +++ b/lua/diffview/vcs/file.lua @@ -142,13 +142,15 @@ function File:_produce_data(callback) end, nil) else self.adapter:show( - { path = self.path, rev = self.rev }, + self.path, + self.rev, function(err, result) if err then - utils.err( - ("Failed to create diff buffer: '%s'"):format(self.path), - true - ) + vim.schedule(function() + utils.err(("Failed to create diff buffer: '%s'"):format( + api.nvim_buf_get_name(self.bufnr) + )) + end) return end diff --git a/lua/diffview/vcs/utils.lua b/lua/diffview/vcs/utils.lua index dfc47107..3f799330 100644 --- a/lua/diffview/vcs/utils.lua +++ b/lua/diffview/vcs/utils.lua @@ -162,7 +162,6 @@ M.diff_file_list = async.wrap(function(adapter, left, right, path_args, dv_opt, ---@diagnostic disable-next-line: redefined-local local err, ufiles = adapter:untracked_files(left, right, opt) - print('untracked: ', #ufiles) if err then errors[#errors+1] = err utils.err("Failed to get git status for untracked files!", true)