diff options
| author | ruki <[email protected]> | 2026-08-11 00:55:18 +0800 |
|---|---|---|
| committer | ruki <[email protected]> | 2026-08-11 00:55:18 +0800 |
| commit | 1cb3fd90ef205361dad1276e58e63d67bda6f283 (patch) | |
| tree | b4c49d889889eb086616d26dae7db12db3f7f20d | |
| parent | c7e176a0674d67e4c6440f2234f730b4ab234c18 (diff) | |
use manifest.txt for addon
| -rw-r--r-- | xmake/actions/addon/main.lua | 8 | ||||
| -rw-r--r-- | xmake/core/package/addon.lua | 85 | ||||
| -rw-r--r-- | xmake/modules/private/action/require/impl/actions/install.lua | 20 |
3 files changed, 59 insertions, 54 deletions
diff --git a/xmake/actions/addon/main.lua b/xmake/actions/addon/main.lua index e3ed7e5be..878b1712d 100644 --- a/xmake/actions/addon/main.lua +++ b/xmake/actions/addon/main.lua @@ -112,15 +112,13 @@ function _install_from_local(dir, name) for _, payloaddir in ipairs(addon.payloads_of(payloadroot)) do os.vcp(path.join(payloadroot, payloaddir), path.join(dstdir, payloaddir)) end - local manifestfile = path.join(dir, "addon.lua") - if os.isfile(manifestfile) then - os.vcp(manifestfile, path.join(dstdir, "addon.lua")) - end + -- we need to roll back the installed payloads if it cannot be registered, e.g. the name conflicts try { function () - addon.register(name, LOCALVERSION) + addon.register(name, LOCALVERSION, manifest and { + description = manifest.description, deps = #manifest.deps > 0 and manifest.deps or nil}) end, catch { diff --git a/xmake/core/package/addon.lua b/xmake/core/package/addon.lua index d6d500e43..727da926a 100644 --- a/xmake/core/package/addon.lua +++ b/xmake/core/package/addon.lua @@ -306,10 +306,10 @@ function addon.owner(scriptdir) local parts = path.split(path.relative(scriptdir, installdir)) if #parts >= 2 then local addondir = path.join(installdir, parts[1], parts[2]) - -- the addon describes itself? the manifest is always authoritative, - -- the directory name is only its normalized form, e.g. "myns::foo" -> "myns_foo" - local manifest = addon.manifest(addondir) - return manifest and manifest.name or parts[1], addondir + -- the registry keeps the raw addon name, the directory name is only + -- its normalized form, e.g. "myns::foo" -> "myns_foo" + local addoninfo = addon.addons()[parts[1]] + return addoninfo and addoninfo.name or parts[1], addondir end return end @@ -387,10 +387,16 @@ end -- get all installed addons -- +-- @param opt the options, e.g. {force = true}, we need it to reload the registry +-- if the addons have been installed by another process +-- -- @return the addons table, e.g. {["hello-world"] = {version = "latest", payloads = {"plugins"}}} -- -function addon.addons() +function addon.addons(opt) local addons = addon._ADDONS + if opt and opt.force then + addons = nil + end if addons == nil then addons = {} local registryfile = addon._registryfile() @@ -520,10 +526,10 @@ function addon.installscript() os.cp(path.join(payloadroot, payloaddir), package:installdir()) end - -- we also install the manifest, so we can get the addon information after installing it - local manifestfile = addon._manifestfile(sourcedir) - if os.isfile(manifestfile) then - os.cp(manifestfile, package:installdir()) + -- we need not install the manifest, the package manifest(manifest.txt) and the addons + -- registry already have all the information, we just pass it to the registration + if manifest then + package:data_set("addon.manifest", manifest) end end end @@ -534,42 +540,25 @@ end -- @param version the addon version, e.g. "1.0.1", "latest" -- @param opt the options, e.g. {description = "...", deps = {"foo"}} -- +-- @note the addon manifest(addon.lua) is only read when installing, everything which +-- is needed later is recorded here, so we never parse it again +-- -- @return true or false and errors -- function addon.register(name, version, opt) opt = opt or {} local dirname = addon.dirname(name) local addondir = path.join(addon.installdir(), dirname, version) - - -- the installed addon describes itself? we prefer its own information - -- - -- @note the deps are duplicated in the package recipe, the recipe is authoritative - -- because xmake needs them before downloading the addon sources, but we should - -- report the mismatch, they must be kept in sync - -- - local description = opt.description - local deps = opt.deps - local manifest = addon.manifest(addondir) - if manifest then - description = manifest.description or description - if deps then - for _, dep in ipairs(manifest.deps) do - if not table.contains(deps, addon.dirname(dep)) then - utils.warning("addon(%s): dep(%s) is declared in its manifest, but not in the package recipe!", name, dep) - end - end - else - deps = {} - for _, dep in ipairs(manifest.deps) do - table.insert(deps, addon.dirname(dep)) - end - deps = #deps > 0 and deps or nil - end - end - local addoninfo = {version = version, - description = description, - deps = deps, + -- we need to keep the raw name, the directory name is only its + -- normalized form, e.g. "myns::foo" -> "myns_foo" + name = name ~= dirname and name or nil, + description = opt.description, + deps = opt.deps, + -- the deps which the addon itself declares in its manifest, they are + -- recorded whenever this addon has one, so that the repositories can + -- check that the manifest and the package recipe are kept in sync + manifest_deps = opt.manifest_deps, payloads = addon.payloads_of(addondir), plugins = addon._plugins_of(addondir), templates = addon._templates_of(addondir)} @@ -648,18 +637,18 @@ function addon.rescan() description = oldaddoninfo.description deps = oldaddoninfo.deps end - -- but we can always get them from the installed manifest - local manifest = addon.manifest(versiondir) - if manifest then - description = manifest.description or description - if #manifest.deps > 0 then - deps = {} - for _, dep in ipairs(manifest.deps) do - table.insert(deps, addon.dirname(dep)) - end + -- but the packages also install their own manifest, we can reuse it + local name + local manifestfile = path.join(versiondir, "manifest.txt") + if os.isfile(manifestfile) then + local manifest = io.load(manifestfile) + if manifest then + name = manifest.name ~= dirname and manifest.name or nil + description = manifest.description or description end end - addons[dirname] = {version = version, description = description, deps = deps, payloads = payloads, + addons[dirname] = {version = version, name = name or (oldaddoninfo and oldaddoninfo.name), + description = description, deps = deps, payloads = payloads, plugins = addon._plugins_of(versiondir), templates = addon._templates_of(versiondir)} end end diff --git a/xmake/modules/private/action/require/impl/actions/install.lua b/xmake/modules/private/action/require/impl/actions/install.lua index fe74e833e..8bc51f4b3 100644 --- a/xmake/modules/private/action/require/impl/actions/install.lua +++ b/xmake/modules/private/action/require/impl/actions/install.lua @@ -510,8 +510,26 @@ function main(package) table.insert(deps, dep:name()) end end + + -- the addon describes itself? we prefer its own description + -- + -- @note the deps are duplicated in its manifest, but the recipe is + -- authoritative, xmake needs them before downloading the addon sources, + -- so we only report the mismatch, they must be kept in sync + local description = package:description() + local manifest = package:data("addon.manifest") + if manifest then + description = manifest.description or description + for _, dep in ipairs(manifest.deps) do + if not (deps and table.contains(deps, dep)) then + wprint("addon(%s): dep(%s) is declared in its manifest, but not in the package recipe!", + package:name(), dep) + end + end + end addon.register(package:name(), package:version_str() or "latest", - {description = package:description(), deps = deps}) + {description = description, deps = deps, + manifest_deps = manifest and manifest.deps or nil}) end installed_now = true end |
