Skip to content

Commit

Permalink
feat: add support for openvsx sources (#1589)
Browse files Browse the repository at this point in the history
  • Loading branch information
williamboman committed Jan 6, 2024
1 parent a09da6a commit 6c68547
Show file tree
Hide file tree
Showing 25 changed files with 638 additions and 265 deletions.
2 changes: 1 addition & 1 deletion lua/mason-core/installer/context.lua
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ function InstallContext:promote_cwd()
end

---@param rel_path string The relative path from the current working directory to change cwd to. Will only restore to the initial cwd after execution of fn (if provided).
---@param fn async (fun())? The function to run in the context of the given path.
---@param fn async (fun(): any)? The function to run in the context of the given path.
function InstallContext:chdir(rel_path, fn)
local old_cwd = self.cwd:get()
self.cwd:set(path.concat { old_cwd, rel_path })
Expand Down
48 changes: 0 additions & 48 deletions lua/mason-core/installer/managers/build.lua

This file was deleted.

126 changes: 126 additions & 0 deletions lua/mason-core/installer/managers/common.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
local Result = require "mason-core.result"
local _ = require "mason-core.functional"
local a = require "mason-core.async"
local async_uv = require "mason-core.async.uv"
local installer = require "mason-core.installer"
local log = require "mason-core.log"
local platform = require "mason-core.platform"
local powershell = require "mason-core.managers.powershell"
local std = require "mason-core.installer.managers.std"

local M = {}

---@class DownloadItem
---@field download_url string
---@field out_file string

---@class FileDownloadSpec
---@field file string | string[]

local get_source_file = _.compose(_.head, _.split ":")
local get_outfile = _.compose(_.last, _.split ":")

---Normalizes file paths from e.g. "file:out-dir/" to "out-dir/file".
---@param file string
local function normalize_file_path(file)
local source_file = get_source_file(file)
local new_path = get_outfile(file)

-- a dir expression (e.g. "libexec/")
if _.matches("/$", new_path) then
return new_path .. source_file
end
return new_path
end

---@generic T : FileDownloadSpec
---@type fun(download: T): T
M.normalize_files = _.evolve {
file = _.cond {
{ _.is "string", normalize_file_path },
{ _.T, _.map(normalize_file_path) },
},
}

---@param download FileDownloadSpec
---@param url_generator fun(file: string): string
---@return DownloadItem[]
function M.parse_downloads(download, url_generator)
local files = download.file
if type(files) == "string" then
files = { files }
end

return _.map(function(file)
local source_file = get_source_file(file)
local out_file = normalize_file_path(file)
return {
download_url = url_generator(source_file),
out_file = out_file,
}
end, files)
end

---@async
---@param ctx InstallContext
---@param downloads DownloadItem[]
---@nodiscard
function M.download_files(ctx, downloads)
return Result.try(function(try)
for __, download in ipairs(downloads) do
a.scheduler()
local out_dir = vim.fn.fnamemodify(download.out_file, ":h")
local out_file = vim.fn.fnamemodify(download.out_file, ":t")
if out_dir ~= "." then
try(Result.pcall(function()
ctx.fs:mkdirp(out_dir)
end))
end
try(ctx:chdir(out_dir, function()
return Result.try(function(try)
try(std.download_file(download.download_url, out_file))
try(std.unpack(out_file))
end)
end))
end
end)
end

---@class BuildInstruction
---@field target? Platform | Platform[]
---@field run string
---@field staged? boolean
---@field env? table<string, string>

---@async
---@param build BuildInstruction
---@return Result
---@nodiscard
function M.run_build_instruction(build)
log.fmt_debug("build: run %s", build)
local ctx = installer.context()
if build.staged == false then
ctx:promote_cwd()
end
return platform.when {
unix = function()
return ctx.spawn.bash {
on_spawn = a.scope(function(_, stdio)
local stdin = stdio[1]
async_uv.write(stdin, "set -euxo pipefail;\n")
async_uv.write(stdin, build.run)
async_uv.shutdown(stdin)
async_uv.close(stdin)
end),
env = build.env,
}
end,
win = function()
return powershell.command(build.run, {
env = build.env,
}, ctx.spawn)
end,
}
end

return M
1 change: 1 addition & 0 deletions lua/mason-core/installer/registry/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ M.register_provider("luarocks", _.lazy_require "mason-core.installer.registry.pr
M.register_provider("npm", _.lazy_require "mason-core.installer.registry.providers.npm")
M.register_provider("nuget", _.lazy_require "mason-core.installer.registry.providers.nuget")
M.register_provider("opam", _.lazy_require "mason-core.installer.registry.providers.opam")
M.register_provider("openvsx", _.lazy_require "mason-core.installer.registry.providers.openvsx")
M.register_provider("pypi", _.lazy_require "mason-core.installer.registry.providers.pypi")

---@param purl Purl
Expand Down
6 changes: 3 additions & 3 deletions lua/mason-core/installer/registry/providers/generic/build.lua
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
local Result = require "mason-core.result"
local _ = require "mason-core.functional"
local build = require "mason-core.installer.managers.build"
local common = require "mason-core.installer.managers.common"
local expr = require "mason-core.installer.registry.expr"
local util = require "mason-core.installer.registry.util"

Expand All @@ -15,7 +15,7 @@ local M = {}
function M.parse(source, purl, opts)
return Result.try(function(try)
---@type BuildInstruction
local build_instruction = try(util.coalesce_by_target(source.build, opts):ok_or "PLATFORM_UNSUPPORTED")
local build_instruction = try(util.coalesce_by_target(source.build, opts))

if build_instruction.env then
local expr_ctx = { version = purl.version, target = build_instruction.target }
Expand All @@ -34,7 +34,7 @@ end
---@param ctx InstallContext
---@param source ParsedGenericBuildSource
function M.install(ctx, source)
return build.run(source.build)
return common.run_build_instruction(source.build)
end

return M
21 changes: 13 additions & 8 deletions lua/mason-core/installer/registry/providers/generic/download.lua
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
local Result = require "mason-core.result"
local _ = require "mason-core.functional"
local common = require "mason-core.installer.managers.common"
local expr = require "mason-core.installer.registry.expr"
local util = require "mason-core.installer.registry.util"

Expand All @@ -17,15 +18,25 @@ local M = {}
---@param opts PackageInstallOpts
function M.parse(source, purl, opts)
return Result.try(function(try)
local download = try(util.coalesce_by_target(source.download, opts):ok_or "PLATFORM_UNSUPPORTED")
local download = try(util.coalesce_by_target(source.download, opts))

local expr_ctx = { version = purl.version }
---@type { files: table<string, string> }
local interpolated_download = try(expr.tbl_interpolate(download, expr_ctx))

---@type DownloadItem[]
local downloads = _.map(function(pair)
---@type DownloadItem
return {
out_file = pair[1],
download_url = pair[2],
}
end, _.to_pairs(interpolated_download.files))

---@class ParsedGenericDownloadSource : ParsedPackageSource
local parsed_source = {
download = interpolated_download,
downloads = downloads,
}
return parsed_source
end)
Expand All @@ -35,13 +46,7 @@ end
---@param ctx InstallContext
---@param source ParsedGenericDownloadSource
function M.install(ctx, source)
local std = require "mason-core.installer.managers.std"
return Result.try(function(try)
for out_file, url in pairs(source.download.files) do
try(std.download_file(url, out_file))
try(std.unpack(out_file))
end
end)
return common.download_files(ctx, source.downloads)
end

return M
6 changes: 3 additions & 3 deletions lua/mason-core/installer/registry/providers/github/build.lua
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
local Result = require "mason-core.result"
local _ = require "mason-core.functional"
local build = require "mason-core.installer.managers.build"
local common = require "mason-core.installer.managers.common"
local expr = require "mason-core.installer.registry.expr"
local util = require "mason-core.installer.registry.util"

Expand All @@ -15,7 +15,7 @@ local M = {}
function M.parse(source, purl, opts)
return Result.try(function(try)
---@type BuildInstruction
local build_instruction = try(util.coalesce_by_target(source.build, opts):ok_or "PLATFORM_UNSUPPORTED")
local build_instruction = try(util.coalesce_by_target(source.build, opts))

local expr_ctx = { version = purl.version }

Expand Down Expand Up @@ -44,7 +44,7 @@ function M.install(ctx, source)
local std = require "mason-core.installer.managers.std"
return Result.try(function(try)
try(std.clone(source.repo, { rev = source.rev }))
try(build.run(source.build))
try(common.run_build_instruction(source.build))
end)
end

Expand Down
Loading

0 comments on commit 6c68547

Please sign in to comment.