aboutsummaryrefslogtreecommitdiffstats
path: root/lua
diff options
context:
space:
mode:
authorphosphene47 <phosphene47@chiya.dev>2021-11-14 18:04:59 +1100
committerphosphene47 <phosphene47@chiya.dev>2021-11-14 18:04:59 +1100
commit78f440dcdd857eb876e459d6bf49510e1d77cdb8 (patch)
tree353bfa981e22c105e762d8cab65cf25903373c52 /lua
parenta8e711124f8f3999f054966064d5d3bb4056f864 (diff)
downloaddep-78f440dcdd857eb876e459d6bf49510e1d77cdb8.tar.gz
dep-78f440dcdd857eb876e459d6bf49510e1d77cdb8.tar.bz2
dep-78f440dcdd857eb876e459d6bf49510e1d77cdb8.zip
Fix many bugs and make things actually work
Diffstat (limited to '')
-rw-r--r--lua/dep.lua575
-rw-r--r--lua/dep/log.lua44
-rw-r--r--lua/dep/proc.lua82
3 files changed, 495 insertions, 206 deletions
diff --git a/lua/dep.lua b/lua/dep.lua
index 8078b62..30e01d4 100644
--- a/lua/dep.lua
+++ b/lua/dep.lua
@@ -3,21 +3,44 @@ local proc = require("dep/proc")
logger:open()
-local base_dir
+local initialized, config_path, base_dir
local packages, package_roots
-local function register(arg)
- if type(arg) ~= "table" then
- arg = { arg }
+local function get_name(id)
+ local name = id:match("^[%w-_.]+/([%w-_.]+)$")
+ if name then
+ return name
+ else
+ error(string.format('invalid name "%s"; must be in the format "user/package"', id))
+ end
+end
+
+local function link_dependency(parent, child)
+ if not parent.dependents[child.id] then
+ parent.dependents[child.id] = child
+ parent.dependents[#parent.dependents + 1] = child
+ end
+
+ if not child.dependencies[parent.id] then
+ child.dependencies[parent.id], child.root = parent, false
+ child.dependencies[#child.dependencies + 1] = parent
+ end
+end
+
+local function register(spec, overrides)
+ overrides = overrides or {}
+
+ if type(spec) ~= "table" then
+ spec = { spec }
end
- local id = arg[1]
+ local id = spec[1]
local package = packages[id]
if not package then
package = {
id = id,
- enabled = false,
+ enabled = true,
exists = false,
added = false,
configured = false,
@@ -31,51 +54,96 @@ local function register(arg)
}
packages[id] = package
+ packages[#packages + 1] = package
end
local prev_dir = package.dir -- optimization
-- meta
- package.name = arg.as or package.name or id:match("^[%w-_.]+/([%w-_.]+)$")
- package.url = arg.url or package.url or ("https://github.com/" .. id .. ".git")
- package.branch = arg.branch or package.branch
+ package.name = spec.as or package.name or get_name(id)
+ package.url = spec.url or package.url or ("https://github.com/" .. id .. ".git")
+ package.branch = spec.branch or package.branch
package.dir = base_dir .. package.name
- package.pin = arg.pin or package.pin
- package.enabled = not arg.disabled and package.enabled
+ package.pin = overrides.pin or spec.pin or package.pin
+ package.enabled = not overrides.disable and not spec.disable and package.enabled
if prev_dir ~= package.dir then
package.exists = vim.fn.isdirectory(package.dir) ~= 0
package.configured = package.exists
end
- table.insert(package.on_setup, arg.setup)
- table.insert(package.on_config, arg.config)
- table.insert(package.on_load, arg[2])
+ package.on_setup[#package.on_setup + 1] = spec.setup
+ package.on_config[#package.on_config + 1] = spec.config
+ package.on_load[#package.on_load + 1] = spec[2]
- for _, req in ipairs(type(arg.requires) == "table" and arg.requires or { arg.requires }) do
- local parent, child = register(req), package
- parent.dependents[child.id] = child
- child.dependencies[parent.id], child.root = parent, false
+ if type(spec.requires) == "table" then
+ for i = 1, #spec.requires do
+ link_dependency(register(spec.requires[i]), package)
+ end
+ elseif spec.requires then
+ link_dependency(register(spec.requires), package)
end
- for _, dep in ipairs(type(arg.deps) == "table" and arg.deps or { arg.deps }) do
- local parent, child = package, register(dep)
- parent.dependents[child.id] = child
- child.dependencies[parent.id], child.root = parent, false
+ if type(spec.deps) == "table" then
+ for i = 1, #spec.deps do
+ link_dependency(package, register(spec.deps[i]))
+ end
+ elseif spec.deps then
+ link_dependency(package, register(spec.deps))
end
+
+ return package
end
-local function register_recursive(list)
- for _, arg in ipairs(list) do
- register(arg)
+local function register_recursive(list, overrides)
+ overrides = overrides or {}
+ overrides = {
+ pin = overrides.pin or list.pin,
+ disable = overrides.disable or list.disable,
+ }
+
+ for i = 1, #list do
+ local ok, err = pcall(register, list[i], overrides)
+ if not ok then
+ error(string.format("%s (spec=%s)", err, vim.inspect(list[i])))
+ end
end
- for _, module in ipairs(list.modules or {}) do
- if type(module) == "string" then
- module = require(module)
+ if list.modules then
+ for i = 1, #list.modules do
+ local name, module = "<unnamed module>", list.modules[i]
+
+ if type(module) == "string" then
+ name, module = module, require(module)
+ end
+
+ name = module.name or name
+
+ local ok, err = pcall(register_recursive, module, overrides)
+ if not ok then
+ error(string.format("%s <- %s", err, name))
+ end
end
+ end
+end
+
+local function sort_dependencies()
+ local function compare(a, b)
+ local a_deps = #a.dependencies
+ local b_deps = #b.dependencies
- register_recursive(module)
+ if a_deps == b_deps then
+ return a.id < b.id
+ else
+ return a_deps < b_deps
+ end
+ end
+
+ table.sort(packages, compare)
+
+ for i = 1, #packages do
+ table.sort(packages[i].dependencies, compare)
+ table.sort(packages[i].dependents, compare)
end
end
@@ -83,23 +151,25 @@ local function find_cycle()
local index = 0
local indexes = {}
local lowlink = {}
- local set = {}
local stack = {}
+ -- use tarjan algorithm to find circular dependencies (strongly connected components)
local function connect(package)
- indexes[package.id], lowlink[package.id], set[package.id] = index, index, true
+ indexes[package.id], lowlink[package.id] = index, index
+ stack[#stack + 1], stack[package.id] = package, true
index = index + 1
- table.insert(stack, package)
- for _, dependent in pairs(package.dependents) do
- if indexes[dependent.id] == nil then
+ for i = 1, #package.dependents do
+ local dependent = package.dependents[i]
+
+ if not indexes[dependent.id] then
local cycle = connect(dependent)
if cycle then
return cycle
else
lowlink[package.id] = math.min(lowlink[package.id], lowlink[dependent.id])
end
- elseif set[dependent.id] then
+ elseif stack[dependent.id] then
lowlink[package.id] = math.min(lowlink[package.id], indexes[dependent.id])
end
end
@@ -109,20 +179,23 @@ local function find_cycle()
local node
repeat
- node = table.remove(stack)
- set[node.id] = nil
- table.insert(cycle, node)
+ node = stack[#stack]
+ stack[#stack], stack[node.id] = nil, nil
+ cycle[#cycle + 1] = node
until node == package
- -- only consider multi-node components
- if #cycle > 2 then
+ -- a node is by definition strongly connected to itself
+ -- ignore single-node components unless it explicitly specified itself as a dependency
+ if #cycle > 2 or package.dependents[package.id] then
return cycle
end
end
end
- for _, package in pairs(packages) do
- if indexes[package.id] == nil then
+ for i = 1, #packages do
+ local package = packages[i]
+
+ if not indexes[package.id] then
local cycle = connect(package)
if cycle then
return cycle
@@ -131,22 +204,41 @@ local function find_cycle()
end
end
+local function ensure_acyclic()
+ local cycle = find_cycle()
+
+ if cycle then
+ local names = {}
+ for i = 1, #cycle do
+ names[i] = cycle[i].id
+ end
+ error("circular dependency detected in package graph: " .. table.concat(names, " -> "))
+ end
+end
+
local function find_roots()
- for _, package in pairs(packages) do
+ for i = 1, #packages do
+ local package = packages[i]
if package.root then
- table.insert(package_roots, package)
+ package_roots[#package_roots + 1] = package
end
end
end
local function run_hooks(package, type)
- for _, cb in ipairs(package["on_" .. type]) do
- local ok, err = pcall(cb)
+ local hooks = package[type]
+
+ for i = 1, #hooks do
+ local ok, err = pcall(hooks[i])
if not ok then
return false, err
end
end
+ if #hooks ~= 0 then
+ logger:log("hook", string.format("ran %d %s for %s", #hooks, #hooks == 1 and "hook" or "hooks", package.id))
+ end
+
return true
end
@@ -155,6 +247,7 @@ local function ensure_added(package)
local ok, err = pcall(vim.cmd, "packadd " .. package.name)
if ok then
package.added = true
+ logger:log("vim", string.format("packadd completed for %s", package.id))
else
return false, err
end
@@ -163,13 +256,21 @@ local function ensure_added(package)
return true
end
-local function configure_recursive(package, force)
+local function configure_recursive(package)
if not package.exists or not package.enabled then
return
end
- if not package.configured or force then
- local ok, err = run_hooks(package, "setup")
+ for i = 1, #package.dependencies do
+ if not package.dependencies[i].configured then
+ return
+ end
+ end
+
+ local propagate = false
+
+ if not package.configured then
+ local ok, err = run_hooks(package, "on_setup")
if not ok then
logger:log("error", string.format("failed to set up %s; reason: %s", package.id, err))
return
@@ -181,96 +282,128 @@ local function configure_recursive(package, force)
return
end
- ok, err = run_hooks(package, "config")
+ ok, err = run_hooks(package, "on_config")
if not ok then
logger:log("error", string.format("failed to configure %s; reason: %s", package.id, err))
return
end
package.configured, package.loaded = true, false
- force = true
+ propagate = true
+
+ logger:log("config", string.format("configured %s", package.id))
end
- for _, dependent in pairs(package.dependents) do
- configure_recursive(dependent, force)
+ for i = 1, #package.dependents do
+ local dependent = package.dependents[i]
+
+ dependent.configured = dependent.configured and not propagate
+ configure_recursive(dependent)
end
end
-local function load_recursive(package, force)
+local function load_recursive(package)
if not package.exists or not package.enabled then
return
end
- if not package.loaded or force then
+ for i = 1, #package.dependencies do
+ if not package.dependencies[i].loaded then
+ return
+ end
+ end
+
+ local propagate = false
+
+ if not package.loaded then
local ok, err = ensure_added(package)
if not ok then
logger:log("error", string.format("failed to configure %s; reason: %s", package.id, err))
return
end
- ok, err = run_hooks(package, "load")
+ ok, err = run_hooks(package, "on_load")
if not ok then
logger:log("error", string.format("failed to load %s; reason: %s", package.id, err))
return
end
package.loaded = true
- force = true
+ propagate = true
+
+ logger:log("load", string.format("loaded %s", package.id))
end
- for _, dependent in pairs(package.dependents) do
+ for i = 1, #package.dependents do
+ local dependent = package.dependents[i]
+
+ dependent.loaded = dependent.loaded and not propagate
load_recursive(dependent, force)
end
end
local function reload_meta()
- vim.cmd([[
- silent! helptags ALL
- silent! UpdateRemotePlugins
- ]])
+ local ok, err = pcall(
+ vim.cmd,
+ [[
+ silent! helptags ALL
+ silent! UpdateRemotePlugins
+ ]]
+ )
+
+ if ok then
+ logger:log("vim", "reloaded helptags and remote plugins")
+ else
+ logger:log("error", string.format("failed to reload helptags and remote plugins; reason: %s", err))
+ end
end
local function reload_all()
- for _, package in pairs(package_roots) do
- configure_recursive(package)
+ for i = 1, #package_roots do
+ configure_recursive(package_roots[i])
end
- for _, package in pairs(package_roots) do
- load_recursive(package)
+ for i = 1, #package_roots do
+ load_recursive(package_roots[i])
end
reload_meta()
end
local function clean()
- vim.loop.fs_scandir(base_dir, function(err, handle)
- if err then
- logger:log("error", string.format("failed to clean; reason: %s", err))
- else
- local queue = {}
+ vim.loop.fs_scandir(
+ base_dir,
+ vim.schedule_wrap(function(err, handle)
+ if err then
+ logger:log("error", string.format("failed to clean; reason: %s", err))
+ else
+ local queue = {}
- while handle do
- local name = vim.loop.fs_scandir_next(handle)
- if name then
- queue[name] = base_dir .. name
- else
- break
+ while handle do
+ local name = vim.loop.fs_scandir_next(handle)
+ if name then
+ queue[name] = base_dir .. name
+ else
+ break
+ end
end
- end
- for _, package in pairs(packages) do
- queue[package.name] = nil
- end
+ for i = 1, #packages do
+ queue[packages[i].name] = nil
+ end
- for name, dir in pairs(queue) do
- -- todo: make this async
- local ok = vim.fn.delete(dir, "rf")
- if not ok then
- logger:log("error", string.format("failed to delete %s", name))
+ for name, dir in pairs(queue) do
+ -- todo: make this async
+ local ok = vim.fn.delete(dir, "rf")
+ if ok then
+ logger:log("clean", string.format("deleted %s", name))
+ else
+ logger:log("error", string.format("failed to delete %s", name))
+ end
end
end
- end
- end)
+ end)
+ )
end
local function sync(package, cb)
@@ -283,34 +416,37 @@ local function sync(package, cb)
return
end
- local function cb_err(err)
+ local function log_err(err)
logger:log("error", string.format("failed to update %s; reason: %s", package.id, err))
- cb(err)
end
- proc.git_current_commit(package.dir, function(err, before)
+ proc.git_rev_parse(package.dir, "HEAD", function(err, before)
if err then
- cb_err(before)
+ log_err(before)
+ cb(err)
else
- proc.git_fetch(package.dir, package.branch or "HEAD", function(err, message)
+ proc.git_fetch(package.dir, "origin", package.branch or "HEAD", function(err, message)
if err then
- cb_err(message)
+ log_err(message)
+ cb(err)
else
- proc.git_reset(package.dir, package.branch or "HEAD", function(err, message)
+ proc.git_rev_parse(package.dir, "FETCH_HEAD", function(err, after)
if err then
- cb_err(message)
+ log_err(after)
+ cb(err)
+ elseif before == after then
+ logger:log("skip", string.format("skipped %s", package.id))
+ cb(err)
else
- proc.get_current_commit(package.dir, function(err, after)
+ proc.git_reset(package.dir, after, function(err, message)
if err then
- cb_err(after)
+ log_err(message)
else
- if before == after then
- logger:log("skip", string.format("skipped %s", package.id))
- else
- package.added, package.configured = false, false
- logger:log("update", string.format("updated %s", package.id))
- end
+ package.added, package.configured = false, false
+ logger:log("update", string.format("updated %s; %s -> %s", package.id, before, after))
end
+
+ cb(err)
end)
end
end)
@@ -326,22 +462,146 @@ local function sync(package, cb)
package.exists, package.added, package.configured = true, false, false
logger:log("install", string.format("installed %s", package.id))
end
+
+ cb(err)
end)
end
end
local function sync_list(list)
local progress = 0
+ local has_errors = false
+
+ local function done(err)
+ progress = progress + 1
+ has_errors = has_errors or err
+
+ if progress == #list then
+ clean()
+ reload_all()
- for _, package in ipairs(list) do
- sync(package, function(err)
- progress = progress + 1
- if progress == #list then
- clean()
- reload_all()
+ if has_errors then
+ logger:log("error", "there were errors during sync; see :messages or :DepLog for more information")
end
- end)
+ end
+ end
+
+ for i = 1, #list do
+ sync(list[i], done)
+ end
+end
+
+local function print_list(list)
+ local window = vim.api.nvim_get_current_win()
+ local buffer = vim.api.nvim_create_buf(true, true)
+ local line = 0
+ local indent = 0
+
+ local function print(chunks)
+ local concat = {}
+ local column = 0
+
+ for i = 1, indent do
+ concat[#concat + 1] = " "
+ column = column + 2
+ end
+
+ if not chunks then
+ chunks = {}
+ elseif type(chunks) == "string" then
+ chunks = { { chunks } }
+ end
+
+ for i = 1, #chunks do
+ local chunk = chunks[i]
+ concat[#concat + 1] = chunk[1]
+ chunk.offset, column = column, column + #chunk[1]
+ end
+
+ vim.api.nvim_buf_set_lines(buffer, line, -1, false, { table.concat(concat) })
+
+ for i = 1, #chunks do
+ local chunk = chunks[i]
+ if chunk[2] then
+ vim.api.nvim_buf_add_highlight(buffer, -1, chunk[2], line, chunk.offset, chunk.offset + #chunk[1])
+ end
+ end
+
+ line = line + 1
+ end
+
+ print("Installed packages:")
+ indent = 1
+
+ local loaded = {}
+
+ local function dry_load(package)
+ for i = 1, #package.dependencies do
+ if not loaded[package.dependencies[i].id] then
+ return
+ end
+ end
+
+ loaded[package.id] = true
+
+ local line = {
+ { "- ", "Comment" },
+ { package.id, "Underlined" },
+ }
+
+ if not package.exists then
+ line[#line + 1] = { " *not installed", "Comment" }
+ end
+
+ if not package.loaded then
+ line[#line + 1] = { " *not loaded", "Comment" }
+ end
+
+ if not package.enabled then
+ line[#line + 1] = { " *disabled", "Comment" }
+ end
+
+ if package.pin then
+ line[#line + 1] = { " *pinned", "Comment" }
+ end
+
+ print(line)
+
+ for i = 1, #package.dependents do
+ dry_load(package.dependents[i])
+ end
end
+
+ for i = 1, #package_roots do
+ dry_load(package_roots[i])
+ end
+
+ indent = 0
+ print()
+ print("Dependency graph:")
+
+ local function walk_graph(package)
+ indent = indent + 1
+
+ print({
+ { "| ", "Comment" },
+ { package.id, "Underlined" },
+ })
+
+ for i = 1, #package.dependents do
+ walk_graph(package.dependents[i])
+ end
+
+ indent = indent - 1
+ end
+
+ for i = 1, #package_roots do
+ walk_graph(package_roots[i])
+ end
+
+ vim.api.nvim_buf_set_option(buffer, "bufhidden", "wipe")
+ vim.api.nvim_buf_set_option(buffer, "modifiable", false)
+ vim.api.nvim_win_set_buf(window, buffer)
end
vim.cmd([[
@@ -349,58 +609,77 @@ vim.cmd([[
command! DepList lua require("dep").list()
command! DepClean lua require("dep").clean()
command! DepLog lua require("dep").open_log()
+ command! DepConfig lua require("dep").open_config()
]])
+local function wrap_api(name, fn)
+ return function(...)
+ if initialized then
+ local ok, err = pcall(fn, ...)
+ if not ok then
+ logger:log("error", err)
+ end
+ else
+ logger:log("error", string.format("cannot call %s; dep is not initialized", name))
+ end
+ end
+end
+
--todo: prevent multiple execution of async routines
return setmetatable({
- sync = function()
- local targets = {}
+ sync = wrap_api("dep.sync", function()
+ sync_list(packages)
+ end),
- for _, package in pairs(packages) do
- table.insert(targets, package)
- end
+ list = wrap_api("dep.list", function()
+ print_list(packages)
+ end),
- sync_list(targets)
- end,
+ clean = wrap_api("dep.clean", clean),
- open_log = function()
+ open_log = wrap_api("dep.open_log", function()
vim.cmd("sp " .. logger.path)
- end,
-}, {
- __call = function(config)
- base_dir = config.base_dir or (vim.fn.stdpath("data") .. "/site/pack/deps/start/")
- packages, package_roots = {}, {}
+ end),
- register_recursive({ "chiyadev/dep", modules = { config } })
-
- local cycle = find_cycle()
- if cycle then
- local names = {}
- for _, package in ipairs(cycle) do
- table.insert(names, package.id)
+ open_config = wrap_api("dep.open_config", function()
+ vim.cmd("sp " .. config_path)
+ end),
+}, {
+ __call = function(self, config)
+ config_path = debug.getinfo(2, "S").source:sub(2)
+ initialized, err = pcall(function()
+ base_dir = config.base_dir or (vim.fn.stdpath("data") .. "/site/pack/deps/start/")
+ packages, package_roots = {}, {}
+
+ register("chiyadev/dep")
+ register_recursive(config)
+ sort_dependencies()
+ ensure_acyclic()
+ find_roots()
+ reload_all()
+
+ local should_sync = function(package)
+ if config.sync == "new" or config.sync == nil then
+ return not package.exists
+ else
+ return config.sync == "always"
+ end
end
- error("circular dependency detected in package graph: " .. table.concat(names, " -> "))
- end
- find_roots()
- reload_all()
+ local targets = {}
- local should_sync = function(package)
- if config.sync == "new" or config.sync == nil then
- return not package.exists
- else
- return config.sync == "always"
+ for i = 1, #packages do
+ local package = packages[i]
+ if should_sync(package) then
+ targets[#targets + 1] = package
+ end
end
- end
- local targets = {}
+ sync_list(targets)
+ end)
- for _, package in pairs(packages) do
- if should_sync(package) then
- table.insert(targets, package)
- end
+ if not initialized then
+ logger:log("error", err)
end
-
- sync_list(targets)
end,
})
diff --git a/lua/dep/log.lua b/lua/dep/log.lua
index 915b214..e61e129 100644
--- a/lua/dep/log.lua
+++ b/lua/dep/log.lua
@@ -4,6 +4,8 @@ local logger = {
}
local colors = {
+ skip = "Constant",
+ clean = "Boolean",
install = "MoreMsg",
update = "WarningMsg",
delete = "Directory",
@@ -32,28 +34,26 @@ function logger:close()
end
end
-function logger:log(op, message, cb)
- if not self.silent and colors[op] then
- vim.api.nvim_echo({
- { "[dep]", "Identifier" },
- { " " },
- { message, colors[op] },
- }, false, {})
- end
-
- if self.pipe then
- local source = debug.getinfo(2, "Sl").short_src
- local message = string.format("[%s] %s: %s\n", os.date(), source, message)
-
- self.pipe:write(
- message,
- vim.schedule_wrap(function(err)
- if cb then
- cb(err)
- end
- end)
- )
- end
+function logger:log(op, message)
+ local source = debug.getinfo(2, "Sl").short_src
+
+ vim.schedule(function()
+ if type(message) ~= "string" then
+ message = vim.inspect(message)
+ end
+
+ if not self.silent and colors[op] then
+ vim.api.nvim_echo({
+ { "[dep]", "Identifier" },
+ { " " },
+ { message, colors[op] },
+ }, true, {})
+ end
+
+ if self.pipe then
+ self.pipe:write(string.format("[%s] %s: %s\n", os.date(), source, message))
+ end
+ end)
end
return logger
diff --git a/lua/dep/proc.lua b/lua/dep/proc.lua
index 38d91fe..376a98c 100644
--- a/lua/dep/proc.lua
+++ b/lua/dep/proc.lua
@@ -2,73 +2,83 @@ local logger = require("dep/log")
local proc = {}
function proc.exec(process, args, cwd, env, cb)
- local out = vim.loop.new_pipe()
- local buffer = {}
+ local handle, pid, buffer = nil, nil, {}
+ local stdout = vim.loop.new_pipe()
+ local stderr = vim.loop.new_pipe()
- local handle = vim.loop.spawn(
+ handle, pid = vim.loop.spawn(
process,
- { args = args, cwd = cwd, env = env, stdio = { nil, out, out } },
+ { args = args, cwd = cwd, env = env, stdio = { nil, stdout, stderr } },
vim.schedule_wrap(function(code)
handle:close()
local output = table.concat(buffer)
+ if output:sub(-1) == "\n" then
+ output = output:sub(1, -2)
+ end
+
logger:log(
process,
- string.format('executed `%s` with args: "%s"\n%s', process, table.concat(args, '", "'), output)
+ string.format(
+ 'executed `%s` (code=%s, pid=%s) with args: "%s"\n%s',
+ process,
+ code,
+ pid,
+ table.concat(args, '", "'),
+ output
+ )
)
- cb(code, output)
+ cb(code ~= 0, output)
end)
)
- vim.loop.read_start(
- out,
- vim.schedule_wrap(function(_, data)
- if data then
- table.insert(buffer, data)
- else
- out:close()
- end
- end)
- )
+ vim.loop.read_start(stdout, function(_, data)
+ if data then
+ buffer[#buffer + 1] = data
+ else
+ stdout:close()
+ end
+ end)
+
+ vim.loop.read_start(stderr, function(_, data)
+ if data then
+ buffer[#buffer + 1] = data
+ else
+ stderr:close()
+ end
+ end)
end
local git_env = { "GIT_TERMINAL_PROMPT=0" }
-function proc.git_current_commit(dir, cb)
- exec("git", { "rev-parse", "HEAD" }, dir, git_env, cb)
+function proc.git_rev_parse(dir, arg, cb)
+ local args = { "rev-parse", "--short", arg }
+
+ proc.exec("git", args, dir, git_env, cb)
end
function proc.git_clone(dir, url, branch, cb)
- local args = { "--depth=1", "--recurse-submodules", "--shallow-submodules", url, dir }
+ local args = { "clone", "--depth=1", "--recurse-submodules", "--shallow-submodules", url, dir }
if branch then
- table.insert(args, "--branch=" .. branch)
+ args[#args + 1] = "--branch=" .. branch
end
- exec("git", args, nil, git_env, cb)
+ proc.exec("git", args, nil, git_env, cb)
end
-function proc.git_fetch(dir, branch, cb)
- local args = { "--depth=1", "--recurse-submodules" }
+function proc.git_fetch(dir, remote, refspec, cb)
+ local args = { "fetch", "--depth=1", "--recurse-submodules", remote, refspec }
- if branch then
- table.insert(args, "origin")
- table.insert(args, branch)
- end
-
- exec("git", args, dir, git_env, cb)
+ proc.exec("git", args, dir, git_env, cb)
end
-function proc.git_reset(dir, branch, cb)
- local args = { "--hard", "--recurse-submodules" }
-
- if branch then
- table.insert("origin/" .. branch)
- end
+function proc.git_reset(dir, treeish, cb)
+ local args = { "reset", "--hard", "--recurse-submodules", treeish, "--" }
- exec("git", args, dir, git_env, cb)
+ proc.exec("git", args, dir, git_env, cb)
end
return proc