Skip to content

Commit

Permalink
feat: use curl as fallback
Browse files Browse the repository at this point in the history
Previously, curl would only be used if gh or glab were not found. But if
the executable was found it was used.

Now, if the the executable returns a non zero exit code, a curl request
will be send. This is specifically useful, if gh or glab are installed
but not setup correctly.
  • Loading branch information
ner0-m committed Nov 22, 2021
1 parent 87397b8 commit f06a278
Show file tree
Hide file tree
Showing 3 changed files with 106 additions and 82 deletions.
72 changes: 28 additions & 44 deletions lua/cmp_git/github.lua
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
local Job = require("plenary.job")
local utils = require("cmp_git.utils")
local sort = require("cmp_git.sort")
local log = require("cmp_git.log")

local GitHub = {
cache = {
Expand All @@ -21,48 +22,33 @@ GitHub.new = function(overrides)
return self
end

local get_command = function(callback, gh_command, curl_url, handle_item)
local command = nil

if false and vim.fn.executable("gh") == 1 and gh_command then
command = gh_command
elseif vim.fn.executable("curl") == 1 and curl_url then
command = {
"curl",
"-s",
"-H",
"'Accept: application/vnd.github.v3+json'",
curl_url,
}

if vim.fn.exists("$GITHUB_API_TOKEN") == 1 then
local token = vim.fn.getenv("GITHUB_API_TOKEN")
local authorization_header = string.format("Authorization: token %s", token)
table.insert(command, "-H")
table.insert(command, authorization_header)
end
else
vim.notify("gh and curl executables not found!")
return
local get_items = function(callback, gh_args, curl_url, handle_item)
local gh_job = utils.build_job("gh", callback, gh_args, handle_item)

curl_args = {
"curl",
"-s",
"-H",
"'Accept: application/vnd.github.v3+json'",
curl_url,
}

if vim.fn.exists("$GITHUB_API_TOKEN") == 1 then
local token = vim.fn.getenv("GITHUB_API_TOKEN")
local authorization_header = string.format("Authorization: token %s", token)
table.insert(curl_args, "-H")
table.insert(curl_args, authorization_header)
end

command.cwd = utils.get_cwd()
command.on_exit = vim.schedule_wrap(function(job)
local result = table.concat(job:result(), "")

local items = utils.handle_response(result, handle_item)
local curl_job = utils.build_job("curl", callback, curl_args, handle_item)

callback({ items = items, isIncomplete = false })
end)

return command
return utils.chain_fallback(gh_job, curl_job)
end

local get_pull_requests_job = function(callback, git_info, trigger_char, config)
return Job:new(get_command(
return get_items(
callback,
{
"gh",
"pr",
"list",
"--repo",
Expand Down Expand Up @@ -105,14 +91,13 @@ local get_pull_requests_job = function(callback, git_info, trigger_char, config)
data = pr,
}
end
))
)
end

local get_issues_job = function(callback, git_info, trigger_char, config)
return Job:new(get_command(
return get_items(
callback,
{
"gh",
"issue",
"list",
"--repo",
Expand Down Expand Up @@ -155,7 +140,7 @@ local get_issues_job = function(callback, git_info, trigger_char, config)
},
}
end
))
)
end

local _get_issues = function(self, callback, git_info, trigger_char, config)
Expand Down Expand Up @@ -234,10 +219,10 @@ function GitHub:get_issues_and_prs(callback, git_info, trigger_char, config)
callback({ items = merged, isIncomplete = false })
else
if git_info.host ~= "github.com" then
vim.notify("Can't fetch Github issues or pull requests, not a github repository")
log.warn("Can't fetch Github issues or pull requests, not a github repository")
return false
elseif git_info.owner == nil and git_info.repo == nil then
vim.notify("Can't figure out git repository or owner")
log.warn("Can't figure out git repository or owner")
return false
end

Expand Down Expand Up @@ -279,8 +264,7 @@ function GitHub:get_mentions(callback, git_info, trigger_char, config)

config = vim.tbl_extend("force", self.config.mentions, config or {})

Job
:new(get_command(
local job = get_items(
function(args)
callback(args)
self.cache.mentions[bufnr] = args.items
Expand All @@ -301,8 +285,8 @@ function GitHub:get_mentions(callback, git_info, trigger_char, config)
data = mention,
}
end
))
:start()
)
job:start()

return true
end
Expand Down
59 changes: 22 additions & 37 deletions lua/cmp_git/gitlab.lua
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
local Job = require("plenary.job")
local utils = require("cmp_git.utils")
local sort = require("cmp_git.sort")
local log = require("cmp_git.log")

local GitLab = {
cache = {
Expand All @@ -25,39 +25,24 @@ local get_project_id = function(git_info)
return utils.url_encode(string.format("%s/%s", git_info.owner, git_info.repo))
end

local get_items = function(callback, glab_command, curl_url, handle_item)
local command = nil

if vim.fn.executable("glab") == 1 and glab_command then
command = glab_command
elseif vim.fn.executable("curl") == 1 and curl_url then
command = {
"curl",
"-s",
curl_url,
}

if vim.fn.exists("$GITLAB_TOKEN") == 1 then
local token = vim.fn.getenv("GITLAB_TOKEN")
local authorization_header = string.format("Authorization: Bearer %s", token)
table.insert(command, "-H")
table.insert(command, authorization_header)
end
else
vim.notify("glab and curl executables not found!")
return
end
local get_items = function(callback, glab_args, curl_url, handle_item)
local glab_job = utils.build_job("glab", callback, glab_args, handle_item)

command.cwd = utils.get_cwd()
command.on_exit = vim.schedule_wrap(function(job)
local result = table.concat(job:result(), "")
curl_args = {
"-s",
curl_url,
}

local items = utils.handle_response(result, handle_item)
if vim.fn.exists("$GITLAB_TOKEN") == 1 then
local token = vim.fn.getenv("GITLAB_TOKEN")
local authorization_header = string.format("Authorization: Bearer %s", token)
table.insert(curl_args, "-H")
table.insert(curl_args, authorization_header)
end

callback({ items = items, isIncomplete = false })
end)
local curl_job = utils.build_job("curl", callback, curl_args, handle_item)

Job:new(command):start()
return utils.chain_fallback(glab_job, curl_job)
end

function GitLab:get_issues(callback, git_info, trigger_char, config)
Expand All @@ -75,13 +60,12 @@ function GitLab:get_issues(callback, git_info, trigger_char, config)
config = vim.tbl_extend("force", self.config.issues, config or {})
local id = get_project_id(git_info)

get_items(
local job = get_items(
function(args)
callback(args)
self.cache.issues[bufnr] = args.items
end,
{
"glab",
"api",
string.format("/projects/%s/issues?per_page=%d&state=%s", id, config.limit, config.state),
},
Expand Down Expand Up @@ -109,6 +93,7 @@ function GitLab:get_issues(callback, git_info, trigger_char, config)
}
end
)
job:start()
return true
end

Expand All @@ -127,13 +112,12 @@ function GitLab:get_mentions(callback, git_info, trigger_char, config)
config = vim.tbl_extend("force", self.config.mentions, config or {})
local id = get_project_id(git_info)

get_items(
local job = get_items(
function(args)
callback(args)
self.cache.mentions[bufnr] = args.items
end,
{
"glab",
"api",
string.format("/projects/%s/users?per_page=%d", id, config.limit),
},
Expand All @@ -150,6 +134,7 @@ function GitLab:get_mentions(callback, git_info, trigger_char, config)
}
end
)
job:start()

return true
end
Expand All @@ -165,17 +150,16 @@ function GitLab:get_merge_requests(callback, git_info, trigger_char, config)
callback({ items = self.cache.merge_requests[bufnr], isIncomplete = false })
return true
end

config = vim.tbl_extend("force", self.config.merge_requests, config or {})
local id = get_project_id(git_info)

get_items(
local job = get_items(
function(args)
callback(args)
self.cache.merge_requests[bufnr] = args.items
end,
{
"glab",
"api",
string.format("/projects/%s/merge_requests?per_page=%d&state=%s", id, config.limit, config.state),
},
Expand All @@ -200,6 +184,7 @@ function GitLab:get_merge_requests(callback, git_info, trigger_char, config)
}
end
)
job:start()

return true
end
Expand Down
57 changes: 56 additions & 1 deletion lua/cmp_git/utils.lua
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
local log = require("cmp_git.log")
local Job = require("plenary.job")

local M = {}

local char_to_hex = function(c)
Expand Down Expand Up @@ -92,12 +95,64 @@ M.get_cwd = function()
return vim.fn.getcwd()
end

M.build_job = function(exec, callback, args, handle_item)
-- TODO: Find a nicer way, that we can keep chaining jobs at call side
if vim.fn.executable(exec) ~= 1 or not args then
log.fmt_debug("Can't work with %s for this call", exec)
return nil
end

return Job:new({
command = exec,
args = args,
cwd = M.get_cwd(),
on_exit = vim.schedule_wrap(function(job, code)
if code ~= 0 then
log.fmt_debug("%s returned with exit code %d", exec, code)
else
log.fmt_debug("%s returned with a result", exec)
local result = table.concat(job:result(), "")

local items = M.handle_response(result, handle_item)

callback({ items = items, isIncomplete = false })
end
end),
})
end

--- Start the second job if the first on fails, handle cases if the first or second job is nil.
--- The last job debug prints on failure
M.chain_fallback = function(first, second)
if first and second then
first:and_then_on_failure(second)
second:after_failure(function(_, code, _)
log.fmt_debug("%s failed with exit code %d, couldn't retrieve any completion info", second.command, code)
end)

return first
elseif first then
first:after_failure(function(_, code, _)
log.fmt_debug("%s failed with exit code %d, couldn't retrieve any completion info", first.command, code)
end)
return first
elseif second then
second:after_failure(function(_, code, _)
log.fmt_debug("%s failed with exit code %d, couldn't retrieve any completion info", second.command, code)
end)
return second
else
log.debug("Neither %s or %s could be found", first.command, second.command)
return nil
end
end

M.handle_response = function(response, handle_item)
local items = {}

local process_data = function(ok, parsed)
if not ok then
vim.notify("Failed to parse api result")
log.warn("Failed to parse api result")
return
end

Expand Down

0 comments on commit f06a278

Please sign in to comment.