aboutsummaryrefslogtreecommitdiffstats
path: root/lua/mason-core/managers/github/init.lua
diff options
context:
space:
mode:
authorWilliam Boman <william@redwill.se>2022-07-08 18:34:38 +0200
committerGitHub <noreply@github.com>2022-07-08 18:34:38 +0200
commit976aa4fbee8a070f362cab6f6ec84e9251a90cf9 (patch)
tree5e8d9c9c59444a25c7801b8f39763c4ba6e1f76d /lua/mason-core/managers/github/init.lua
parentfeat: add gotests, gomodifytags, impl (#28) (diff)
downloadmason-976aa4fbee8a070f362cab6f6ec84e9251a90cf9.tar
mason-976aa4fbee8a070f362cab6f6ec84e9251a90cf9.tar.gz
mason-976aa4fbee8a070f362cab6f6ec84e9251a90cf9.tar.bz2
mason-976aa4fbee8a070f362cab6f6ec84e9251a90cf9.tar.lz
mason-976aa4fbee8a070f362cab6f6ec84e9251a90cf9.tar.xz
mason-976aa4fbee8a070f362cab6f6ec84e9251a90cf9.tar.zst
mason-976aa4fbee8a070f362cab6f6ec84e9251a90cf9.zip
refactor: add mason-schemas and mason-core modules (#29)
* refactor: add mason-schemas and move generated filetype map to mason-lspconfig * refactor: add mason-core module
Diffstat (limited to 'lua/mason-core/managers/github/init.lua')
-rw-r--r--lua/mason-core/managers/github/init.lua171
1 files changed, 171 insertions, 0 deletions
diff --git a/lua/mason-core/managers/github/init.lua b/lua/mason-core/managers/github/init.lua
new file mode 100644
index 00000000..55f3600f
--- /dev/null
+++ b/lua/mason-core/managers/github/init.lua
@@ -0,0 +1,171 @@
+local installer = require "mason-core.installer"
+local std = require "mason-core.managers.std"
+local client = require "mason-core.managers.github.client"
+local platform = require "mason-core.platform"
+local Result = require "mason-core.result"
+local _ = require "mason-core.functional"
+local settings = require "mason.settings"
+
+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
+
+---@param repo string
+---@param tag string
+local function with_tag_receipt(repo, tag)
+ return function()
+ local ctx = installer.context()
+ ctx.receipt:with_primary_source {
+ type = "github_tag",
+ repo = repo,
+ tag = tag,
+ }
+ 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 = _.coalesce(opts.version, ctx.requested_version):or_else_get(function()
+ return client
+ .fetch_latest_release(opts.repo)
+ :map(_.prop "tag_name")
+ :get_or_throw "Failed to fetch latest release from GitHub API. Refer to :h mason-errors-github-api for more information."
+ end)
+ ---@type string
+ local asset_file
+ if type(opts.asset_file) == "function" then
+ asset_file = opts.asset_file(release)
+ else
+ asset_file = opts.asset_file
+ end
+ if not asset_file then
+ error(
+ (
+ "Could not find which release file to download.\nMost likely the current operating system, architecture (%s), or libc (%s) is not supported."
+ ):format(platform.arch, platform.get_libc()),
+ 0
+ )
+ end
+ local download_url = settings.current.github.download_url_template: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
+
+---@async
+---@param opts {repo: string, version: Optional|nil}
+function M.tag(opts)
+ local ctx = installer.context()
+ local tag = _.coalesce(opts.version, ctx.requested_version):or_else_get(function()
+ return client.fetch_latest_tag(opts.repo):get_or_throw "Failed to fetch latest tag from GitHub API."
+ end)
+
+ return {
+ tag = tag,
+ with_receipt = with_tag_receipt(opts.repo, tag),
+ }
+end
+
+---@param filename string
+---@param processor async fun(opts: table)
+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(opts)
+ 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(opts)
+ std.untarxz("archive.tar.xz", { strip_components = opts.strip_components })
+end)
+
+M.untargz_release_file = release_file_processor("archive.tar.gz", function(opts)
+ std.untar("archive.tar.gz", { strip_components = opts.strip_components })
+end)
+
+---@async
+---@param opts {repo: string, out_file:string, asset_file: string|fun(release: string):string}
+function M.download_release_file(opts)
+ local release_file_source = M.release_file(opts)
+ std.download_file(release_file_source.download_url, assert(opts.out_file, "out_file is required"))
+ return release_file_source
+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)
+ local gzipped_file = ("%s.gz"):format(assert(opts.out_file, "out_file must be specified"))
+ std.download_file(release_file_source.download_url, gzipped_file)
+ std.gunzip(gzipped_file)
+ return release_file_source
+end
+
+---@async
+---@param receipt InstallReceipt
+function M.check_outdated_primary_package_release(receipt)
+ local source = receipt.primary_source
+ if source.type ~= "github_release" and source.type ~= "github_release_file" then
+ return Result.failure "Receipt does not have a primary source of type (github_release|github_release_file)."
+ end
+ return client.fetch_latest_release(source.repo, { tag_name_pattern = source.tag_name_pattern }):map_catching(
+ ---@param latest_release GitHubRelease
+ function(latest_release)
+ if source.release ~= latest_release.tag_name then
+ return {
+ name = source.repo,
+ current_version = source.release,
+ latest_version = latest_release.tag_name,
+ }
+ end
+ error "Primary package is not outdated."
+ end
+ )
+end
+
+---@async
+---@param receipt InstallReceipt
+function M.check_outdated_primary_package_tag(receipt)
+ local source = receipt.primary_source
+ if source.type ~= "github_tag" then
+ return Result.failure "Receipt does not have a primary source of type github_tag."
+ end
+ return client.fetch_latest_tag(source.repo):map_catching(function(latest_tag)
+ if source.tag ~= latest_tag then
+ return {
+ name = source.repo,
+ current_version = source.tag,
+ latest_version = latest_tag,
+ }
+ end
+ error "Primary package is not outdated."
+ end)
+end
+
+return M