Skip to content

Commit

Permalink
refactor(receipt): change receipt structure and remove old builder AP…
Browse files Browse the repository at this point in the history
…Is (#1521)
  • Loading branch information
williamboman committed Nov 8, 2023
1 parent 013c513 commit ec7501e
Show file tree
Hide file tree
Showing 11 changed files with 207 additions and 104 deletions.
6 changes: 1 addition & 5 deletions lua/mason-core/installer/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,7 @@ end
local function build_receipt(context)
return Result.pcall(function()
log.fmt_debug("Building receipt for %s", context.package)
return context.receipt
:with_name(context.package.name)
:with_schema_version("1.1")
:with_completion_time(vim.loop.gettimeofday())
:build()
return context.receipt:with_name(context.package.name):with_completion_time(vim.loop.gettimeofday()):build()
end)
end

Expand Down
6 changes: 3 additions & 3 deletions lua/mason-core/installer/linker.lua
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,12 @@ local LinkContext = {
---@param link_context LinkContext
local function unlink(receipt, link_context)
return Result.pcall(function()
local links = receipt.links[link_context.type]
local links = receipt:get_links()[link_context.type]
if not links then
return
end
for linked_file in pairs(links) do
if receipt.schema_version == "1.0" and link_context == LinkContext.BIN and platform.is.win then
if receipt:get_schema_version() == "1.0" and link_context == LinkContext.BIN and platform.is.win then
linked_file = linked_file .. ".cmd"
end
local share_path = link_context.prefix(linked_file)
Expand All @@ -39,7 +39,7 @@ end
---@param receipt InstallReceipt
---@nodiscard
function M.unlink(pkg, receipt)
log.fmt_debug("Unlinking %s", pkg, receipt.links)
log.fmt_debug("Unlinking %s", pkg, receipt:get_links())
return Result.try(function(try)
try(unlink(receipt, LinkContext.BIN))
try(unlink(receipt, LinkContext.SHARE))
Expand Down
3 changes: 2 additions & 1 deletion lua/mason-core/installer/registry/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ local util = require "mason-core.installer.registry.util"

local M = {}

---@type table<RegistryPackageSpecSchema, boolean>
M.SCHEMA_CAP = _.set_of {
"registry+v1",
}
Expand Down Expand Up @@ -203,7 +204,7 @@ function M.compile(spec, opts)
try(link.opt(ctx, spec, parsed.purl, parsed.source))
end

ctx.receipt:with_primary_source {
ctx.receipt:with_source {
type = ctx.package.spec.schema,
id = Purl.compile(parsed.purl),
}
Expand Down
10 changes: 7 additions & 3 deletions lua/mason-core/package/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,11 @@ local PackageMt = { __index = Package }
---@field since string
---@field message string

---@alias RegistryPackageSpecSchema
--- | '"registry+v1"'

---@class RegistryPackageSpec
---@field schema '"registry+v1"'
---@field schema RegistryPackageSpecSchema
---@field name string
---@field description string
---@field homepage string
Expand Down Expand Up @@ -231,8 +234,9 @@ function Package:get_installed_version()
:and_then(
---@param receipt InstallReceipt
function(receipt)
if receipt.primary_source.id then
return Purl.parse(receipt.primary_source.id):map(_.prop "version"):ok()
local source = receipt:get_source()
if source.id then
return Purl.parse(source.id):map(_.prop "version"):ok()
else
return Optional.empty()
end
Expand Down
124 changes: 36 additions & 88 deletions lua/mason-core/receipt.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3,36 +3,20 @@ local M = {}
---@alias InstallReceiptSchemaVersion
---| '"1.0"'
---| '"1.1"'
---| '"1.2"'

---@alias InstallReceiptSourceType
---| '"npm"'
---| '"pip3"'
---| '"gem"'
---| '"go"'
---| '"cargo"'
---| '"opam"'
---| '"dotnet"'
---| '"unmanaged"'
---| '"system"'
---| '"jdtls"'
---| '"git"'
---| '"github_tag"'
---| '"github_release"'
---| '"github_release_file"'

---@alias InstallReceiptSource {type: InstallReceiptSourceType}
---@alias InstallReceiptSource {type: RegistryPackageSpecSchema, id: string}

---@class InstallReceiptLinks
---@field bin? table<string, string>
---@field share? table<string, string>
---@field opt? table<string, string>

---@class InstallReceipt<T> : { primary_source: T }
---@class InstallReceipt
---@field public name string
---@field public schema_version InstallReceiptSchemaVersion
---@field public metrics {start_time:integer, completion_time:integer}
---@field public primary_source InstallReceiptSource
---@field public secondary_sources InstallReceiptSource[]
---@field public source InstallReceiptSource
---@field public links InstallReceiptLinks
local InstallReceipt = {}
InstallReceipt.__index = InstallReceipt
Expand All @@ -45,6 +29,32 @@ function InstallReceipt.from_json(json)
return InstallReceipt.new(json)
end

function InstallReceipt:get_name()
return self.name
end

function InstallReceipt:get_schema_version()
return self.schema_version
end

---@param version string
function InstallReceipt:is_schema_min(version)
local semver = require "mason-vendor.semver"
return semver(self.schema_version) >= semver(version)
end

---@return InstallReceiptSource
function InstallReceipt:get_source()
if self:is_schema_min "1.2" then
return self.source
end
return self.primary_source --[[@as InstallReceiptSource]]
end

function InstallReceipt:get_links()
return self.links
end

---@async
---@param cwd string
function InstallReceipt:write(cwd)
Expand All @@ -54,15 +64,12 @@ function InstallReceipt:write(cwd)
end

---@class InstallReceiptBuilder
---@field private secondary_sources InstallReceiptSource[]
---@field private links InstallReceiptLinks
---@field private epoch_time number
---@field links InstallReceiptLinks
local InstallReceiptBuilder = {}
InstallReceiptBuilder.__index = InstallReceiptBuilder

function InstallReceiptBuilder.new()
return setmetatable({
secondary_sources = {},
links = {
bin = vim.empty_dict(),
share = vim.empty_dict(),
Expand All @@ -77,21 +84,9 @@ function InstallReceiptBuilder:with_name(name)
return self
end

---@param version InstallReceiptSchemaVersion
function InstallReceiptBuilder:with_schema_version(version)
self.schema_version = version
return self
end

---@param source InstallReceiptSource
function InstallReceiptBuilder:with_primary_source(source)
self.primary_source = source
return self
end

---@param source InstallReceiptSource
function InstallReceiptBuilder:with_secondary_source(source)
table.insert(self.secondary_sources, source)
function InstallReceiptBuilder:with_source(source)
self.source = source
return self
end

Expand Down Expand Up @@ -128,68 +123,21 @@ end

function InstallReceiptBuilder:build()
assert(self.name, "name is required")
assert(self.schema_version, "schema_version is required")
assert(self.start_time, "start_time is required")
assert(self.completion_time, "completion_time is required")
assert(self.primary_source, "primary_source is required")
assert(self.source, "source is required")
return InstallReceipt.new {
name = self.name,
schema_version = self.schema_version,
schema_version = "1.2",
metrics = {
start_time = self.start_time,
completion_time = self.completion_time,
},
primary_source = self.primary_source,
secondary_sources = self.secondary_sources,
source = self.source,
links = self.links,
}
end

---@class InstallReceiptPackageSource
---@field type string
---@field package string

---@param type InstallReceiptSourceType
local function package_source(type)
---@param pkg string
---@return InstallReceiptPackageSource
return function(pkg)
return { type = type, package = pkg }
end
end

InstallReceiptBuilder.npm = package_source "npm"
InstallReceiptBuilder.pip3 = package_source "pip3"
InstallReceiptBuilder.gem = package_source "gem"
InstallReceiptBuilder.go = package_source "go"
InstallReceiptBuilder.dotnet = package_source "dotnet"
InstallReceiptBuilder.cargo = package_source "cargo"
InstallReceiptBuilder.composer = package_source "composer"
InstallReceiptBuilder.opam = package_source "opam"
InstallReceiptBuilder.luarocks = package_source "luarocks"

InstallReceiptBuilder.unmanaged = { type = "unmanaged" }

---@param repo string
---@param release string
function InstallReceiptBuilder.github_release(repo, release)
return {
type = "github_release",
repo = repo,
release = release,
}
end

---@param dependency string
function InstallReceiptBuilder.system(dependency)
return { type = "system", dependency = dependency }
end

---@param remote_url string
function InstallReceiptBuilder.git_remote(remote_url)
return { type = "git", remote = remote_url }
end

M.InstallReceiptBuilder = InstallReceiptBuilder
M.InstallReceipt = InstallReceipt

Expand Down
2 changes: 1 addition & 1 deletion lua/mason/ui/instance.lua
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@ local function hydrate_detailed_package_state(pkg)
---@param receipt InstallReceipt
function(receipt)
mutate_state(function(state)
state.packages.states[pkg.name].linked_executables = receipt.links.bin
state.packages.states[pkg.name].linked_executables = receipt:get_links().bin
end)
end
)
Expand Down
23 changes: 23 additions & 0 deletions tests/fixtures/receipts/1.0.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"schema_version": "1.0",
"primary_source": {
"type": "npm",
"package": "@angular/language-server"
},
"links": {
"bin": {
"ngserver": "node_modules/.bin/ngserver"
}
},
"metrics": {
"start_time": 1694752057715,
"completion_time": 1694752066467
},
"secondary_sources": [
{
"type": "npm",
"package": "typescript"
}
],
"name": "angular-language-server"
}
27 changes: 27 additions & 0 deletions tests/fixtures/receipts/1.1.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"schema_version": "1.1",
"metrics": {
"start_time": 1694752380220,
"completion_time": 1694752386830
},
"links": {
"share": {},
"opt": {},
"bin": {
"ngserver": "node_modules/.bin/ngserver"
}
},
"name": "angular-language-server",
"primary_source": {
"type": "registry+v1",
"id": "pkg:npm/%40angular/language-server@16.1.8",
"source": {
"extra_packages": [
"typescript@5.1.3"
],
"version": "16.1.8",
"package": "@angular/language-server"
}
},
"secondary_sources": []
}
19 changes: 19 additions & 0 deletions tests/fixtures/receipts/1.2.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"name": "angular-language-server",
"links": {
"bin": {
"ngserver": "node_modules/.bin/ngserver"
},
"opt": {},
"share": {}
},
"metrics": {
"completion_time": 1694752770559,
"start_time": 1694752764840
},
"schema_version": "1.2",
"source": {
"type": "registry+v1",
"id": "pkg:npm/%40angular/language-server@16.1.8"
}
}
5 changes: 2 additions & 3 deletions tests/mason-core/installer/installer_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -87,12 +87,11 @@ describe("installer", function()
local receipt = vim.json.decode(arg)
assert.is_true(match.tbl_containing {
name = "dummy",
primary_source = match.same {
source = match.same {
type = handle.package.spec.schema,
id = handle.package.spec.source.id,
},
secondary_sources = match.same {},
schema_version = "1.1",
schema_version = "1.2",
metrics = match.is_table(),
links = match.same {
bin = { executable = "target" },
Expand Down
Loading

0 comments on commit ec7501e

Please sign in to comment.