summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorruki <[email protected]>2026-08-08 23:17:52 +0800
committerruki <[email protected]>2026-08-09 18:28:59 +0800
commitcf62f410738a7489fe052d183bcf616ecf5f7067 (patch)
treeea9d09e1d05c3a392e9f08688618a1a9663625b3
parent8564ea66201d1398cb8ee5b91efc784a379c4a64 (diff)
add addon search
-rw-r--r--tests/actions/addon/test.lua114
-rw-r--r--xmake/actions/addon/main.lua137
-rw-r--r--xmake/actions/addon/xmake.lua4
-rw-r--r--xmake/core/package/addon.lua19
-rw-r--r--xmake/core/sandbox/modules/import/core/package/addon.lua1
-rw-r--r--xmake/modules/package/manager/xmake/search_package.lua4
-rw-r--r--xmake/modules/private/action/require/search.lua8
-rw-r--r--xmake/modules/private/xrepo/action/remove.lua18
-rw-r--r--xmake/modules/private/xrepo/action/search.lua6
-rw-r--r--xmake/modules/private/xrepo/quick_search/cache.lua68
10 files changed, 230 insertions, 149 deletions
diff --git a/tests/actions/addon/test.lua b/tests/actions/addon/test.lua
index 17a5dc33c..d393c0545 100644
--- a/tests/actions/addon/test.lua
+++ b/tests/actions/addon/test.lua
@@ -68,6 +68,9 @@ function _mock_repo(basenames)
cache.repositories[reponame] = {repodir}
io.save(cachefile, cache)
+ -- we need to clear the quick search cache, it will be rebuilt on the next search
+ os.tryrm(path.join(global.cachedir(), "quick_search"))
+
local function cleanup()
for _, name in ipairs(names) do
os.tryrm(path.join(global.directory(), "addons", name))
@@ -78,49 +81,65 @@ function _mock_repo(basenames)
cache.repositories[reponame] = nil
end
io.save(cachefile, cache)
+ os.tryrm(path.join(global.cachedir(), "quick_search"))
os.tryrm(repodir)
end
return reponame, names, cleanup
end
+-- run the given function with a mocked repository, we always clean it up even if the test fails
+function _with_repo(basenames, func)
+ local reponame, names, cleanup = _mock_repo(basenames)
+ try
+ {
+ function ()
+ func(reponame, names)
+ end,
+ finally
+ {
+ cleanup
+ }
+ }
+end
+
-- install an addon from a repository, by plain name and by repo@name
function test_install_from_repo(t)
- local reponame, names, cleanup = _mock_repo({"hello"})
- local name = names[1]
+ _with_repo({"hello"}, function (reponame, names)
+ local name = names[1]
- -- install by plain name (searched across all repositories)
- os.runv("xmake", {"addon", "--install", "-y", name})
- t:require(os.iorunv("xmake", {name}):find(name, 1, true))
+ -- install by plain name (searched across all repositories)
+ os.runv("xmake", {"addon", "--install", "-y", name})
+ t:require(os.iorunv("xmake", {name}):find(name, 1, true))
- -- reinstall by repo@name
- os.runv("xmake", {"addon", "--remove", name})
- os.runv("xmake", {"addon", "--install", "-y", reponame .. "@" .. name})
- t:require(os.iorunv("xmake", {name}):find(name, 1, true))
+ -- reinstall by repo@name
+ os.runv("xmake", {"addon", "--remove", name})
+ os.runv("xmake", {"addon", "--install", "-y", reponame .. "@" .. name})
+ t:require(os.iorunv("xmake", {name}):find(name, 1, true))
- os.runv("xmake", {"addon", "--remove", name})
- cleanup()
+ os.runv("xmake", {"addon", "--remove", name})
+ end)
end
-- the templates of an installed addon can be used by `xmake create`
function test_install_templates(t)
- local _, names, cleanup = _mock_repo({"hello"})
- local name = names[1]
- os.runv("xmake", {"addon", "--install", "-y", name})
+ _with_repo({"hello"}, function (_, names)
+ local name = names[1]
+ os.runv("xmake", {"addon", "--install", "-y", name})
- -- this template should be listed and grouped by its addon name
- local out = os.iorunv("xmake", {"create", "--list"})
- t:require(out:find(name, 1, true))
+ -- this template should be listed and grouped by its addon name
+ local out = os.iorunv("xmake", {"create", "--list"})
+ t:require(out:find(name, 1, true))
- -- we can create a new project from it
- local projectdir = os.tmpfile() .. ".addon-project"
- os.tryrm(projectdir)
- os.runv("xmake", {"create", "-l", "c", "-t", name, "-P", projectdir})
- t:require(os.isfile(path.join(projectdir, "xmake.lua")))
- t:require(os.isfile(path.join(projectdir, "src", "main.c")))
+ -- we can create a new project from it
+ local projectdir = os.tmpfile() .. ".addon-project"
+ os.tryrm(projectdir)
+ os.runv("xmake", {"create", "-l", "c", "-t", name, "-P", projectdir})
+ t:require(os.isfile(path.join(projectdir, "xmake.lua")))
+ t:require(os.isfile(path.join(projectdir, "src", "main.c")))
- os.tryrm(projectdir)
- os.runv("xmake", {"addon", "--remove", name})
- cleanup()
+ os.tryrm(projectdir)
+ os.runv("xmake", {"addon", "--remove", name})
+ end)
end
-- install an addon from a local directory, then remove it
@@ -140,24 +159,39 @@ function test_install_from_local(t)
os.tryrm(path.directory(dir))
end
--- --list shows the installed and available addons
+-- --list shows the installed addons and their payloads
function test_list(t)
- local _, names, cleanup = _mock_repo({"hello", "world"})
+ _with_repo({"hello", "world"}, function (_, names)
+
+ -- install the first addon, leave the second only available
+ os.runv("xmake", {"addon", "--install", "-y", names[1]})
+ local out = os.iorunv("xmake", {"addon", "--list"})
+ t:require(out:find("the installed addons:", 1, true))
+ t:require(out:find(names[1], 1, true))
- -- install the first addon, leave the second only available
- os.runv("xmake", {"addon", "--install", "-y", names[1]})
- local out = os.iorunv("xmake", {"addon", "--list"})
- t:require(out:find("the installed addons:", 1, true))
- t:require(out:find(names[1], 1, true))
- t:require(out:find(names[2], 1, true))
- t:require(out:find("xmake addon --install " .. names[2], 1, true))
+ -- the payloads of the installed addon should be shown, e.g. (plugins, templates)
+ t:require(out:find("plugins", 1, true))
+ t:require(out:find("templates", 1, true))
+
+ -- the addon which is not installed should be shown in the available addons
+ t:require(out:find("the available addons:", 1, true))
+ t:require(out:find(names[2], 1, true))
+
+ os.runv("xmake", {"addon", "--remove", names[1]})
+ end)
+end
- -- the payloads of the installed addon should be shown, e.g. (latest, plugins, templates)
- t:require(out:find("plugins", 1, true))
- t:require(out:find("templates", 1, true))
+-- --search finds the addons in the repositories, it reuses `xrepo search --addon`
+function test_search(t)
+ _with_repo({"hello"}, function (_, names)
+ local name = names[1]
+ local out = os.iorunv("xmake", {"addon", "--search", name})
+ t:require(out:find(name, 1, true))
- os.runv("xmake", {"addon", "--remove", names[1]})
- cleanup()
+ -- the addons should not be found by the package search
+ local packages_out = os.iorunv("xrepo", {"search", name})
+ t:require_not(packages_out:find(name, 1, true))
+ end)
end
-- invalid installs should fail
diff --git a/xmake/actions/addon/main.lua b/xmake/actions/addon/main.lua
index 52cb2376b..f3da68d8e 100644
--- a/xmake/actions/addon/main.lua
+++ b/xmake/actions/addon/main.lua
@@ -21,13 +21,16 @@
-- imports
import("core.base.option")
import("core.package.addon")
-import("core.package.repository")
import("devel.git")
import("private.action.require.impl.environment")
+import("private.action.require.impl.search_packages")
-- the version directory name for the addons installed from git urls or local directories
local LOCALVERSION = "latest"
+-- the maximum number of the available addons shown by `--list`
+local LISTLIMIT = 10
+
-- validate an addon directory name
function _check_addon_name(name)
assert(type(name) == "string" and name ~= "" and name ~= "." and not name:find("..", 1, true) and not name:find("[/\\:]"), "invalid addon name(%s)!", name)
@@ -46,23 +49,9 @@ function _get_addondir(name, version)
return addondir
end
--- get local and global repositories, with local taking precedence
-function _repositories()
- return table.join(repository.repositories({global = false}), repository.repositories({global = true}))
-end
-
--- install an addon from the given repository or the first repository containing it
-function _install_from_repo(name, reponame)
-
- -- check addon name
- _check_addon_name(name)
-
- -- do install
- local installname = name
- if reponame then
- installname = reponame .. "@" .. name
- end
- local argv = {"lua", "private.xrepo", "install", "--addon"}
+-- run the given xrepo action for the addons, e.g. install, remove, search
+function _xrepo(action, names)
+ local argv = {"lua", "private.xrepo", action, "--addon"}
-- we need to pass the common options to the sub-process, e.g. -y, -v, -D
if option.get("yes") then
table.insert(argv, "-y")
@@ -73,10 +62,16 @@ function _install_from_repo(name, reponame)
if option.get("diagnosis") then
table.insert(argv, "-D")
end
- table.insert(argv, installname)
+ table.join2(argv, names)
os.execv(os.programfile(), argv)
end
+-- install an addon from the given repository or the first repository containing it
+function _install_from_repo(name, reponame)
+ _check_addon_name(name)
+ _xrepo("install", {reponame and (reponame .. "@" .. name) or name})
+end
+
-- install a single addon from a source directory (as the given name, default to the directory name)
function _install_from_local(dir, name)
assert(os.isdir(dir), "addon path(%s) not found!", dir)
@@ -148,27 +143,16 @@ function _install()
environment.leave()
end
--- remove the given installed addon
+-- remove the given installed addons
function _remove()
local names = assert(option.get("addons"), "please specify the addon name to be removed!")
- assert(#names == 1, "please specify only one addon name to be removed!")
- local name = names[1]
- local dir = _get_addondir(name)
- assert(os.isdir(dir), "addon(%s) not found!", name)
- os.rmdir(dir)
- addon.unregister(name)
- cprint("${color.success}remove ${bright}%s${clear} ok!", name)
+ _xrepo("remove", names)
end
--- get the description of an addon from its package description file
-function _addon_description(dir)
- local filepath = path.join(dir, "xmake.lua")
- if os.isfile(filepath) then
- local content = io.readfile(filepath)
- if content then
- return content:match("set_description%s*%(\"(.-)\"%)")
- end
- end
+-- search the addons from the repositories
+function _search()
+ local patterns = assert(option.get("addons"), "please specify the addon name pattern to be searched!")
+ _xrepo("search", patterns)
end
-- collect the installed addons from the addons registry
@@ -186,70 +170,57 @@ function _collect_installed_addons()
return entries
end
--- collect the addons in the given repository, they follow the packages layout (addons/<first-letter>/<name>)
-function _collect_repo_addons(root, seen)
- local entries = {}
- for _, dir in ipairs(os.dirs(path.join(root, "*", "*"))) do
- local name = path.filename(dir)
- if os.isfile(path.join(dir, "xmake.lua")) and not seen[name] then
- seen[name] = true
- table.insert(entries, {name = name, description = _addon_description(dir)})
- end
+-- print an addon entry, e.g. -> serial-monitor v1.0.1: monitor the serial port output (in xmake-repo)
+function _print_addon(entry, suffix)
+ local title = entry.name
+ if entry.version then
+ title = title .. " " .. entry.version
end
- return entries
+ local description = entry.description and (": " .. entry.description) or ""
+ cprint(" ${color.dump.reference}->${clear} ${color.dump.string}%s${clear}%s%s", title, description, suffix or "")
end
--- print an addon entry with its description aligned on the right
-function _print_addon(name, description, width, note)
- local suffix = description or ""
- if note then
- suffix = suffix ~= "" and (suffix .. " " .. note) or note
- end
- if suffix ~= "" then
- local padding = math.max(width - #name, 1)
- cprint(" ${color.dump.string}%s${clear}%s%s", name, (" "):rep(padding), suffix)
- else
- cprint(" ${color.dump.string}%s${clear}", name)
+-- get the addons in the repositories, we reuse the packages search here
+function _collect_repo_addons(exclude)
+ local entries = {}
+ for _, results in pairs(search_packages({"*"}, {kind = "addon", description = false})) do
+ for _, result in ipairs(results) do
+ if not exclude[result.name] then
+ table.insert(entries, result)
+ end
+ end
end
+ table.sort(entries, function (a, b) return a.name < b.name end)
+ return entries
end
-- list all addons
function _list()
- local seen = {}
- local installed = _collect_installed_addons()
- for _, entry in ipairs(installed) do
- seen[entry.name] = true
- end
- local avail = {}
- for _, repo in ipairs(_repositories()) do
- table.join2(avail, _collect_repo_addons(path.join(repo:directory(), "addons"), seen))
- end
- -- compute the alignment width from all addon names
- local width = 0
- for _, entries in ipairs({installed, avail}) do
- for _, entry in ipairs(entries) do
- width = math.max(width, #entry.name + 4)
- end
- end
-
- -- installed addons
+ -- show the installed addons
+ local installed = _collect_installed_addons()
+ local exclude = {}
cprint("${bright}the installed addons:${clear}")
if #installed > 0 then
for _, entry in ipairs(installed) do
- local note = string.format("(%s, %s)", entry.version, table.concat(entry.payloads, ", "))
- _print_addon(entry.name, entry.description, width, note)
+ exclude[entry.name] = true
+ _print_addon(entry, string.format(" ${dim}(%s)${clear}", table.concat(entry.payloads, ", ")))
end
else
print(" (none)")
end
- -- addons available in repositories (not yet installed)
- cprint("${bright}available in configured repositories:${clear}")
+ -- show the addons in the repositories, we only show the first ones if there are too many
+ local avail = _collect_repo_addons(exclude)
+ cprint("${bright}the available addons:${clear} ${dim}(run `xmake addon --install <name>` to install," ..
+ " `--search <pattern>` to search)${clear}")
if #avail > 0 then
- for _, entry in ipairs(avail) do
- local note = string.format("(run xmake addon --install %s to install)", entry.name)
- _print_addon(entry.name, entry.description, width, note)
+ for idx, entry in ipairs(avail) do
+ if idx > LISTLIMIT then
+ cprint(" ${dim}... and %d more${clear}", #avail - LISTLIMIT)
+ break
+ end
+ _print_addon(entry, entry.reponame and string.format(" ${dim}(in %s)${clear}", entry.reponame) or nil)
end
else
print(" (none)")
@@ -269,6 +240,8 @@ function main()
_remove()
elseif option.get("list") then
_list()
+ elseif option.get("search") then
+ _search()
elseif option.get("clear") then
_clear()
end
diff --git a/xmake/actions/addon/xmake.lua b/xmake/actions/addon/xmake.lua
index 8394c110b..240fef5bf 100644
--- a/xmake/actions/addon/xmake.lua
+++ b/xmake/actions/addon/xmake.lua
@@ -26,7 +26,8 @@ task("addon")
description = "Manage addons of xmake.",
options = {
{'i', "install", "k", nil, "Install addons."},
- {'r', "remove", "k", nil, "Remove the given installed addon."},
+ {'r', "remove", "k", nil, "Remove the given installed addons."},
+ {'s', "search", "k", nil, "Search the addons from the repositories."},
{'l', "list", "k", nil, "List all installed addons."},
{'c', "clear", "k", nil, "Clear all installed addons."},
{nil, "addons", "vs", nil, "The addon paths, urls or names.",
@@ -38,6 +39,7 @@ task("addon")
" $ xmake addon --install xmake-repo@serial-monitor",
" $ xmake addon --install serial-monitor",
" $ xmake addon --remove serial-monitor",
+ " $ xmake addon --search serial",
" $ xmake addon --list"}
}
}
diff --git a/xmake/core/package/addon.lua b/xmake/core/package/addon.lua
index d433bdf8a..78830d266 100644
--- a/xmake/core/package/addon.lua
+++ b/xmake/core/package/addon.lua
@@ -182,6 +182,25 @@ function addon.register(name, version, opt)
addon._save(addons)
end
+-- remove the given installed addon
+--
+-- @param name the addon name
+-- @return true or false and errors
+--
+function addon.remove(name)
+ local dirname = addon.dirname(name)
+ local installdir = path.join(addon.installdir(), dirname)
+ if not os.isdir(installdir) then
+ return false, string.format("addon(%s) not found!", name)
+ end
+ local ok, errors = os.rm(installdir)
+ if not ok then
+ return false, errors
+ end
+ addon.unregister(name)
+ return true
+end
+
-- unregister the given addon
function addon.unregister(name)
local dirname = addon.dirname(name)
diff --git a/xmake/core/sandbox/modules/import/core/package/addon.lua b/xmake/core/sandbox/modules/import/core/package/addon.lua
index ecbd95f2b..2885bd45f 100644
--- a/xmake/core/sandbox/modules/import/core/package/addon.lua
+++ b/xmake/core/sandbox/modules/import/core/package/addon.lua
@@ -36,6 +36,7 @@ sandbox_core_package_addon.addons = addon.addons
sandbox_core_package_addon.addondir = addon.addondir
sandbox_core_package_addon.register = addon.register
sandbox_core_package_addon.unregister = addon.unregister
+sandbox_core_package_addon.remove = addon.remove
sandbox_core_package_addon.rescan = addon.rescan
sandbox_core_package_addon.clear = addon.clear
diff --git a/xmake/modules/package/manager/xmake/search_package.lua b/xmake/modules/package/manager/xmake/search_package.lua
index 32991ae3e..a5ed3caf8 100644
--- a/xmake/modules/package/manager/xmake/search_package.lua
+++ b/xmake/modules/package/manager/xmake/search_package.lua
@@ -23,7 +23,7 @@ import("core.base.semver")
import("private.xrepo.quick_search.cache")
function _search_package(packages, name, opt)
- for _, packageinfo in ipairs(cache.find(name, {description = opt.description ~= false})) do
+ for _, packageinfo in ipairs(cache.find(name, {description = opt.description ~= false, kind = opt.kind})) do
local packagename = packageinfo.name
local packagedata = packageinfo.data
@@ -59,7 +59,7 @@ end
-- search package using the xmake package manager
--
-- @param name the package name with pattern
--- @param opt the options, e.g. {require_version = "1.x"}
+-- @param opt the options, e.g. {require_version = "1.x", kind = "addon"}
--
function main(name, opt)
opt = opt or {}
diff --git a/xmake/modules/private/action/require/search.lua b/xmake/modules/private/action/require/search.lua
index e714c6c19..a0f98e0d9 100644
--- a/xmake/modules/private/action/require/search.lua
+++ b/xmake/modules/private/action/require/search.lua
@@ -20,6 +20,7 @@
-- imports
import("core.base.task")
+import("core.base.option")
import("private.action.require.impl.utils.filter")
import("private.action.require.impl.repository")
import("private.action.require.impl.environment")
@@ -41,11 +42,14 @@ function main(names)
task.run("repo", {update = true})
end
+ -- we only search the addon packages if `--addon` is enabled
+ local kind = option.get("addon") and "addon" or nil
+
-- show title
- print("The package names:")
+ print(kind == "addon" and "The addon names:" or "The package names:")
-- search packages
- for name, packages in pairs(search_packages(names)) do
+ for name, packages in pairs(search_packages(names, {kind = kind})) do
if #packages > 0 then
-- show name
diff --git a/xmake/modules/private/xrepo/action/remove.lua b/xmake/modules/private/xrepo/action/remove.lua
index ed92a83b8..adfec92c0 100644
--- a/xmake/modules/private/xrepo/action/remove.lua
+++ b/xmake/modules/private/xrepo/action/remove.lua
@@ -20,6 +20,7 @@
-- imports
import("core.base.option")
+import("core.package.addon")
import("private.action.require.impl.remove_packages", {alias = "remove_all_packages"})
-- get menu options
@@ -44,6 +45,9 @@ function menu_options()
{nil, "toolchain", "kv", nil, "Set the toolchain name." },
{nil, "toolchain_host", "kv", nil, "Set the host toolchain name." },
{ },
+ {nil, "addon", "k", nil, "Remove the given installed addon packages.",
+ "e.g.",
+ " - xrepo remove --addon serial-monitor" },
{nil, "all", "k", nil, "Remove all packages and ignore extra package configs.",
"If `--all` is enabled, the package name parameter will support lua pattern",
"e.g.",
@@ -193,10 +197,22 @@ function _remove_packages(packages)
os.vexecv(os.programfile(), require_argv)
end
+-- remove the given installed addons
+function _remove_addons(names)
+ for _, name in ipairs(names) do
+ local ok, errors = addon.remove(name)
+ assert(ok, errors)
+ cprint("${color.success}remove ${bright}%s${clear} ok!", name)
+ end
+end
+
-- main entry
function main()
local packages = option.get("packages")
- if option.get("all") then
+ if option.get("addon") then
+ assert(packages, "please specify the addons to be removed.")
+ _remove_addons(packages)
+ elseif option.get("all") then
remove_all_packages(packages)
elseif packages then
_remove_packages(packages)
diff --git a/xmake/modules/private/xrepo/action/search.lua b/xmake/modules/private/xrepo/action/search.lua
index d389e3833..c532af44e 100644
--- a/xmake/modules/private/xrepo/action/search.lua
+++ b/xmake/modules/private/xrepo/action/search.lua
@@ -30,6 +30,9 @@ function menu_options()
-- menu options
local options =
{
+ {nil, "addon", "k", nil, "Search the addon packages from <repository>/addons/",
+ "e.g.",
+ " - xrepo search --addon serial"},
{nil, "packages", "vs", nil, "The packages list (support lua pattern).",
"e.g.",
" - xrepo search zlib boost",
@@ -80,6 +83,9 @@ function _search_packages(packages)
if option.get("diagnosis") then
table.insert(require_argv, "-D")
end
+ if option.get("addon") then
+ table.insert(require_argv, "--addon")
+ end
table.join2(require_argv, packages)
os.vexecv(os.programfile(), require_argv)
end
diff --git a/xmake/modules/private/xrepo/quick_search/cache.lua b/xmake/modules/private/xrepo/quick_search/cache.lua
index cf75a212d..43af417a8 100644
--- a/xmake/modules/private/xrepo/quick_search/cache.lua
+++ b/xmake/modules/private/xrepo/quick_search/cache.lua
@@ -25,20 +25,36 @@ import("private.action.require.impl.repository")
local cache = globalcache.cache("quick_search")
+-- get the cache key of the given package
+--
+-- @note the addons are stored with the `addon::` prefix,
+-- because an addon and a package may have the same name
+--
+function _cachekey(packagename, kind)
+ return kind == "addon" and ("addon::" .. packagename) or packagename
+end
+
-- search package directories from repositories
+--
+-- the packages are stored in <repodir>/packages/<first-letter>/<name>,
+-- and the addons are stored in <repodir>/addons/<first-letter>/<name>
+--
function _list_package_dirs()
-- find the package directories from all repositories
local unique = {}
local packageinfos = {}
for _, repo in ipairs(repository.repositories()) do
- for _, file in ipairs(os.files(path.join(repo:directory(), "packages", "*", "*", "xmake.lua"))) do
- local dir = path.directory(file)
- local subdirname = path.basename(path.directory(dir))
- if #subdirname == 1 then -- ignore l/luajit/port/xmake.lua
- local packagename = path.filename(dir)
- if not unique[packagename] then
- table.insert(packageinfos, {name = packagename, repo = repo, packagedir = dir})
- unique[packagename] = true
+ for _, rootinfo in ipairs({{rootdir = "packages"}, {rootdir = "addons", kind = "addon"}}) do
+ for _, file in ipairs(os.files(path.join(repo:directory(), rootinfo.rootdir, "*", "*", "xmake.lua"))) do
+ local dir = path.directory(file)
+ local subdirname = path.basename(path.directory(dir))
+ if #subdirname == 1 then -- ignore l/luajit/port/xmake.lua
+ local packagename = path.filename(dir)
+ local cachekey = _cachekey(packagename, rootinfo.kind)
+ if not unique[cachekey] then
+ table.insert(packageinfos, {name = packagename, kind = rootinfo.kind, repo = repo, packagedir = dir})
+ unique[cachekey] = true
+ end
end
end
end
@@ -57,7 +73,9 @@ end
function update()
for _, packageinfo in ipairs(_list_package_dirs()) do
local package = core_package.load_from_repository(packageinfo.name, packageinfo.packagedir, {repo = packageinfo.repo})
- cache:set(packageinfo.name, {
+ cache:set(_cachekey(packageinfo.name, packageinfo.kind), {
+ name = packageinfo.name,
+ kind = packageinfo.kind,
reponame = package:repo() and package:repo():name(),
description = package:description(),
versions = package:versions(),
@@ -79,22 +97,30 @@ function get()
end
-- find package
+--
+-- @param name the package name (support lua pattern)
+-- @param opt the options, e.g. {prefix = true, description = true, kind = "addon"}
+--
function find(name, opt)
_init()
opt = opt or {}
local list_result = {}
- for packagename, packagedata in pairs(cache:data()) do
- local found = false
- if opt.prefix then
- found = packagename:startswith(name)
- else
- found = packagename:find(path.pattern(name))
- end
- if not found and opt.description and packagedata.description and packagedata.description:find(name) then
- found = true
- end
- if found then
- table.insert(list_result, {name = packagename, data = packagedata})
+ for cachekey, packagedata in pairs(cache:data()) do
+ -- we only search the packages with the given kind, e.g. nil (package), "addon"
+ local packagename = packagedata.name or cachekey
+ if packagedata.kind == opt.kind then
+ local found = false
+ if opt.prefix then
+ found = packagename:startswith(name)
+ else
+ found = packagename:find(path.pattern(name))
+ end
+ if not found and opt.description and packagedata.description and packagedata.description:find(name) then
+ found = true
+ end
+ if found then
+ table.insert(list_result, {name = packagename, data = packagedata})
+ end
end
end
return list_result