aboutsummaryrefslogtreecommitdiffstats
path: root/lua/nvim-lsp-installer/core/managers/github
diff options
context:
space:
mode:
authorWilliam Boman <william@redwill.se>2022-04-21 12:09:59 +0200
committerGitHub <noreply@github.com>2022-04-21 12:09:59 +0200
commitb68fcc6bb2c770495ff8e2508c06dfdd49abcc80 (patch)
treedf7c71efb59958deb21a18eeccf3e3c43c4cd704 /lua/nvim-lsp-installer/core/managers/github
parentrun autogen_metadata.lua (diff)
downloadmason-b68fcc6bb2c770495ff8e2508c06dfdd49abcc80.tar
mason-b68fcc6bb2c770495ff8e2508c06dfdd49abcc80.tar.gz
mason-b68fcc6bb2c770495ff8e2508c06dfdd49abcc80.tar.bz2
mason-b68fcc6bb2c770495ff8e2508c06dfdd49abcc80.tar.lz
mason-b68fcc6bb2c770495ff8e2508c06dfdd49abcc80.tar.xz
mason-b68fcc6bb2c770495ff8e2508c06dfdd49abcc80.tar.zst
mason-b68fcc6bb2c770495ff8e2508c06dfdd49abcc80.zip
chore: refactor remaining installers to async impl (#616)
Diffstat (limited to 'lua/nvim-lsp-installer/core/managers/github')
-rw-r--r--lua/nvim-lsp-installer/core/managers/github/client.lua51
-rw-r--r--lua/nvim-lsp-installer/core/managers/github/init.lua89
2 files changed, 123 insertions, 17 deletions
diff --git a/lua/nvim-lsp-installer/core/managers/github/client.lua b/lua/nvim-lsp-installer/core/managers/github/client.lua
index a8766748..7cf80cf2 100644
--- a/lua/nvim-lsp-installer/core/managers/github/client.lua
+++ b/lua/nvim-lsp-installer/core/managers/github/client.lua
@@ -7,14 +7,13 @@ local list_find_first = Data.list_find_first
local M = {}
----@alias GitHubRelease {tag_name:string, prerelease: boolean, draft: boolean}
+---@alias GitHubReleaseAsset {url: string, id: integer, name: string, browser_download_url: string, created_at: string, updated_at: string, size: integer, download_count: integer}
+---@alias GitHubRelease {tag_name: string, prerelease: boolean, draft: boolean, assets:GitHubReleaseAsset[]}
---@alias GitHubTag {name: string}
----@async
----@param repo string The GitHub repo ("username/repo").
-function M.fetch_releases(repo)
- log.fmt_trace("Fetching GitHub releases for repo=%s", repo)
- local path = ("repos/%s/releases"):format(repo)
+---@param path string
+---@return Result @JSON decoded response.
+local function api_call(path)
return spawn.gh({ "api", path })
:map(function(result)
return result.stdout
@@ -25,10 +24,31 @@ function M.fetch_releases(repo)
:map_catching(vim.json.decode)
end
+---@async
+---@param repo string @The GitHub repo ("username/repo").
+function M.fetch_releases(repo)
+ log.fmt_trace("Fetching GitHub releases for repo=%s", repo)
+ local path = ("repos/%s/releases"):format(repo)
+ return api_call(path):map_err(function()
+ return ("Failed to fetch releases for GitHub repository %s."):format(repo)
+ end)
+end
+
+---@async
+---@param repo string @The GitHub repo ("username/repo").
+---@param tag_name string @The tag_name of the release to fetch.
+function M.fetch_release(repo, tag_name)
+ log.fmt_trace("Fetching GitHub release for repo=%s, tag_name=%s", repo, tag_name)
+ local path = ("repos/%s/releases/tags/%s"):format(repo, tag_name)
+ return api_call(path):map_err(function()
+ return ("Failed to fetch release %q for GitHub repository %s."):format(tag_name, repo)
+ end)
+end
+
---@alias FetchLatestGithubReleaseOpts {tag_name_pattern:string}
---@async
----@param repo string The GitHub repo ("username/repo").
+---@param repo string @The GitHub repo ("username/repo").
---@param opts FetchLatestGithubReleaseOpts|nil
---@return Result @of GitHubRelease
function M.fetch_latest_release(repo, opts)
@@ -61,21 +81,18 @@ function M.fetch_latest_release(repo, opts)
end
---@async
----@param repo string The GitHub repo ("username/repo").
+---@param repo string @The GitHub repo ("username/repo").
+---@return Result @of [GitHubTag[]]
function M.fetch_tags(repo)
local path = ("repos/%s/tags"):format(repo)
- return spawn.gh({ "api", path })
- :map(function(result)
- return result.stdout
- end)
- :recover_catching(function()
- return fetch(("https://api.github.com/%s"):format(path)):get_or_throw()
- end)
- :map_catching(vim.json.decode)
+ return api_call(path):map_err(function()
+ return ("Failed to fetch tags for GitHub repository %s."):format(repo)
+ end)
end
---@async
----@param repo string The GitHub repo ("username/repo").
+---@param repo string @The GitHub repo ("username/repo").
+---@return Result @of [GitHubTag]
function M.fetch_latest_tag(repo)
return M.fetch_tags(repo):map_catching(function(tags)
if vim.tbl_count(tags) == 0 then
diff --git a/lua/nvim-lsp-installer/core/managers/github/init.lua b/lua/nvim-lsp-installer/core/managers/github/init.lua
new file mode 100644
index 00000000..32afc03c
--- /dev/null
+++ b/lua/nvim-lsp-installer/core/managers/github/init.lua
@@ -0,0 +1,89 @@
+local installer = require "nvim-lsp-installer.core.installer"
+local std = require "nvim-lsp-installer.core.managers.std"
+local client = require "nvim-lsp-installer.core.managers.github.client"
+local platform = require "nvim-lsp-installer.platform"
+
+local M = {}
+
+---@param repo string
+---@param asset_file string
+---@param release string
+local function with_release_file_receipt(repo, asset_file, release)
+ return function()
+ local ctx = installer.context()
+ ctx.receipt:with_primary_source {
+ type = "github_release_file",
+ repo = repo,
+ file = asset_file,
+ release = release,
+ }
+ end
+end
+
+---@async
+---@param opts {repo: string, version: Optional|nil, asset_file: string|fun(release: string):string}
+function M.release_file(opts)
+ local ctx = installer.context()
+ local release = (opts.version or ctx.requested_version):or_else_get(function()
+ return client.fetch_latest_release(opts.repo)
+ :map(function(release)
+ return release.tag_name
+ end)
+ :get_or_throw "Failed to fetch latest release from GitHub API."
+ end)
+ ---@type string
+ local asset_file = type(opts.asset_file) == "function" and opts.asset_file(release) or opts.asset_file
+ if not asset_file then
+ error(
+ (
+ "Could not find which release file to download. Most likely the current operating system, architecture (%s), or libc (%s) is not supported."
+ ):format(platform.arch, platform.get_libc())
+ )
+ end
+ local download_url = ("https://github.com/%s/releases/download/%s/%s"):format(opts.repo, release, asset_file)
+ return {
+ release = release,
+ download_url = download_url,
+ asset_file = asset_file,
+ with_receipt = with_release_file_receipt(opts.repo, download_url, release),
+ }
+end
+
+---@param filename string
+---@param processor async fun()
+local function release_file_processor(filename, processor)
+ ---@async
+ ---@param opts {repo: string, asset_file: string|fun(release: string):string}
+ return function(opts)
+ local release_file_source = M.release_file(opts)
+ std.download_file(release_file_source.download_url, filename)
+ processor(release_file_source)
+ return release_file_source
+ end
+end
+
+M.unzip_release_file = release_file_processor("archive.zip", function()
+ std.unzip("archive.zip", ".")
+end)
+
+M.untarxz_release_file = release_file_processor("archive.tar.xz", function()
+ std.untarxz "archive.tar.xz"
+end)
+
+M.untargz_release_file = release_file_processor("archive.tar.gz", function()
+ std.untar "archive.tar.gz"
+end)
+
+---@async
+---@param opts {repo: string, out_file:string, asset_file: string|fun(release: string):string}
+function M.gunzip_release_file(opts)
+ local release_file_source = M.release_file(opts)
+ std.download_file(
+ release_file_source.download_url,
+ ("%s.gz"):format(assert(opts.out_file, "out_file must be specified"))
+ )
+ std.gunzip(opts.out_file)
+ return release_file_source
+end
+
+return M