diff options
| author | William Boman <william@redwill.se> | 2022-04-21 12:09:59 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-04-21 12:09:59 +0200 |
| commit | b68fcc6bb2c770495ff8e2508c06dfdd49abcc80 (patch) | |
| tree | df7c71efb59958deb21a18eeccf3e3c43c4cd704 /lua/nvim-lsp-installer/core/managers/github | |
| parent | run autogen_metadata.lua (diff) | |
| download | mason-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.lua | 51 | ||||
| -rw-r--r-- | lua/nvim-lsp-installer/core/managers/github/init.lua | 89 |
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 |
