From 3768256956060188d14127867dbe63603bd4ae9e Mon Sep 17 00:00:00 2001
From: Folke Lemaitre <folke.lemaitre@gmail.com>
Date: Mon, 28 Nov 2022 13:10:52 +0100
Subject: [PATCH] refactor: pipelines now always run sequential

---
 lua/lazy/manage/init.lua     |  4 +--
 lua/lazy/manage/runner.lua   | 56 ++++++++++++------------------------
 lua/lazy/manage/task/git.lua | 27 ++++++++---------
 tests/manage/runner_spec.lua | 13 ++++++++-
 tests/manage/task_spec.lua   |  2 +-
 5 files changed, 45 insertions(+), 57 deletions(-)

diff --git a/lua/lazy/manage/init.lua b/lua/lazy/manage/init.lua
index f6c1a40..905693c 100644
--- a/lua/lazy/manage/init.lua
+++ b/lua/lazy/manage/init.lua
@@ -47,7 +47,7 @@ end
 ---@param opts? ManagerOpts
 function M.install(opts)
   M.run({
-    pipeline = { "git.install", { "plugin.docs", "plugin.run" } },
+    pipeline = { "git.install", "plugin.docs", "plugin.run" },
     plugins = function(plugin)
       return plugin.uri and not plugin._.installed
     end,
@@ -57,7 +57,7 @@ end
 ---@param opts? ManagerOpts
 function M.update(opts)
   M.run({
-    pipeline = { "git.update", { "plugin.docs", "plugin.run" }, "git.log" },
+    pipeline = { "git.update", "plugin.docs", "plugin.run", "wait", "git.log" },
     plugins = function(plugin)
       return plugin.uri and plugin._.installed
     end,
diff --git a/lua/lazy/manage/runner.lua b/lua/lazy/manage/runner.lua
index d70e094..f1f808c 100644
--- a/lua/lazy/manage/runner.lua
+++ b/lua/lazy/manage/runner.lua
@@ -1,7 +1,7 @@
 local Task = require("lazy.manage.task")
 local Config = require("lazy.core.config")
 
----@alias LazyPipeline (TaskType|TaskType[])[]
+---@alias LazyPipeline TaskType[]
 
 ---@class RunnerOpts
 ---@field pipeline LazyPipeline
@@ -38,57 +38,36 @@ end
 ---@param plugin LazyPlugin
 ---@param pipeline LazyPipeline
 function Runner:_run(plugin, pipeline)
-  if #pipeline == 0 then
-    return
-  end
-  local ops = table.remove(pipeline, 1)
-  if ops == "wait" then
+  ---@type TaskType
+  local op = table.remove(pipeline, 1)
+  if op == "wait" then
     return table.insert(self._waiting, function()
       self:_run(plugin, pipeline)
     end)
   end
-
-  ops = type(ops) == "string" and { ops } or ops
-  ---@cast ops TaskType[]
-
-  ---@type LazyTask[]
-  local tasks = {}
-
-  local function on_done()
-    for _, task in ipairs(tasks) do
-      if task.error or not task:is_done() then
-        return
-      end
+  self:queue(plugin, op, function(task)
+    if not (task and task.error) and #pipeline > 0 then
+      self:_run(plugin, pipeline)
     end
-    self:_run(plugin, pipeline)
-  end
-
-  for _, op in ipairs(ops) do
-    local task = self:queue(plugin, op, { on_done = on_done })
-    if task then
-      table.insert(tasks, task)
-    end
-  end
-
-  for _, task in ipairs(tasks) do
-    task:start()
-  end
+  end)
 end
 
 ---@param plugin LazyPlugin
 ---@param task_type TaskType
----@param opts? TaskOptions
+---@param on_done fun(task?:LazyTask)
 ---@return LazyTask?
-function Runner:queue(plugin, task_type, opts)
+function Runner:queue(plugin, task_type, on_done)
   local def = vim.split(task_type, ".", { plain = true })
   assert(#def == 2)
   ---@type LazyTaskDef
   local task_def = require("lazy.manage.task." .. def[1])[def[2]]
   assert(task_def)
-  if not task_def.needed or task_def.needed(plugin, self._opts) then
-    local task = Task.new(plugin, def[2], task_def.run, opts)
+  if not (task_def.skip and task_def.skip(plugin, self._opts)) then
+    local task = Task.new(plugin, def[2], task_def.run, { on_done = on_done })
     table.insert(self._tasks, task)
-    return task
+    task:start()
+  else
+    on_done()
   end
 end
 
@@ -106,10 +85,11 @@ function Runner:start()
       end
     end
     if #self._waiting > 0 then
-      for _, cb in ipairs(self._waiting) do
+      local waiting = self._waiting
+      self._waiting = {}
+      for _, cb in ipairs(waiting) do
         cb()
       end
-      self._waiting = {}
       return
     end
     check:stop()
diff --git a/lua/lazy/manage/task/git.lua b/lua/lazy/manage/task/git.lua
index e42918a..dee0b64 100644
--- a/lua/lazy/manage/task/git.lua
+++ b/lua/lazy/manage/task/git.lua
@@ -5,11 +5,11 @@ local Git = require("lazy.manage.git")
 local M = {}
 
 M.log = {
-  needed = function(plugin, opts)
-    if opts.interactive ~= true or not Util.file_exists(plugin.dir .. "/.git") then
+  skip = function(plugin, opts)
+    if not (opts.interactive and Util.file_exists(plugin.dir .. "/.git")) then
       return false
     end
-    return plugin._.updated == nil or plugin._.updated.from ~= plugin._.updated.to
+    return plugin._.updated and plugin._.updated.from == plugin._.updated.to
   end,
   run = function(self)
     local args = {
@@ -36,7 +36,11 @@ M.log = {
 
 M.update = {
   run = function(self)
-    if Util.file_exists(self.plugin.uri) then
+    if self.plugin._.is_local ~= self.plugin._.is_symlink then
+      -- FIXME: should change here and in install
+      error("incorrect local")
+    end
+    if self.plugin._.is_local then
       if vim.loop.fs_realpath(self.plugin.uri) ~= vim.loop.fs_realpath(self.plugin.dir) then
         vim.loop.fs_unlink(self.plugin.dir)
         vim.loop.fs_symlink(self.plugin.uri, self.plugin.dir, {
@@ -47,7 +51,6 @@ M.update = {
     else
       local args = {
         "pull",
-        "--tags",
         "--recurse-submodules",
         "--update-shallow",
         "--progress",
@@ -74,29 +77,23 @@ M.update = {
 
 M.install = {
   run = function(self)
-    if Util.file_exists(self.plugin.uri) then
-      vim.loop.fs_symlink(self.plugin.uri, self.plugin.dir, {
-        dir = true,
-      })
+    if self.plugin._.is_local then
+      vim.loop.fs_symlink(self.plugin.uri, self.plugin.dir, { dir = true })
       vim.opt.runtimepath:append(self.plugin.uri)
     else
       local args = {
         "clone",
         self.plugin.uri,
-        -- "--depth=1",
         "--filter=blob:none",
-        -- "--filter=tree:0",
         "--recurse-submodules",
         "--single-branch",
         "--shallow-submodules",
+        "--no-checkout",
         "--progress",
       }
 
       if self.plugin.branch then
-        vim.list_extend(args, {
-          "-b",
-          self.plugin.branch,
-        })
+        vim.list_extend(args, { "-b", self.plugin.branch })
       end
 
       table.insert(args, self.plugin.dir)
diff --git a/tests/manage/runner_spec.lua b/tests/manage/runner_spec.lua
index b8fdc9e..c400e8a 100644
--- a/tests/manage/runner_spec.lua
+++ b/tests/manage/runner_spec.lua
@@ -1,7 +1,7 @@
 local Runner = require("lazy.manage.runner")
 
 describe("runner", function()
-  local plugins = { { name = "plugin1" }, { name = "plugin2" } }
+  local plugins = { { name = "plugin1", _ = {} }, { name = "plugin2", _ = {} } }
 
   ---@type {plugin:string, task:string}[]
   local runs = {}
@@ -10,6 +10,11 @@ describe("runner", function()
   end)
 
   package.loaded["lazy.manage.task.test"] = {}
+  package.loaded["lazy.manage.task.test"]["skip"] = {
+    skip = function()
+      return true
+    end,
+  }
   for i = 1, 10 do
     package.loaded["lazy.manage.task.test"]["test" .. i] = {
       ---@param task LazyTask
@@ -32,6 +37,12 @@ describe("runner", function()
     assert.equal(4, #runs)
   end)
 
+  it("handles skips", function()
+    local runner = Runner.new({ plugins = plugins, pipeline = { "test.test1", "test.skip", "test.test2" } })
+    runner:start()
+    assert.equal(4, #runs)
+  end)
+
   it("aborts on error", function()
     local runner = Runner.new({ plugins = plugins, pipeline = { "test.test1", "test.error1", "test.test2" } })
     runner:start()
diff --git a/tests/manage/task_spec.lua b/tests/manage/task_spec.lua
index 090d76a..e886484 100644
--- a/tests/manage/task_spec.lua
+++ b/tests/manage/task_spec.lua
@@ -1,7 +1,7 @@
 local Task = require("lazy.manage.task")
 
 describe("task", function()
-  local plugin = { name = "test" }
+  local plugin = { name = "test", _ = {} }
 
   local done = false
   local error = nil