summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorruki <[email protected]>2026-08-01 08:53:30 +0800
committerruki <[email protected]>2026-08-01 08:53:30 +0800
commit8d7a74306556a4c292c0345f1a9aa833116ebcec (patch)
tree49b0b3ae14157a3f24193623d6adb69e282675e9
parentf91724eb1d7f80e81772ad6f20b03b2a0cff8125 (diff)
improve tests
-rw-r--r--tests/plugins/repository/test.lua135
-rw-r--r--xmake/plugins/plugin/main.lua26
-rw-r--r--xmake/plugins/plugin/xmake.lua12
3 files changed, 90 insertions, 83 deletions
diff --git a/tests/plugins/repository/test.lua b/tests/plugins/repository/test.lua
index 4f1347317..f1cfba8c7 100644
--- a/tests/plugins/repository/test.lua
+++ b/tests/plugins/repository/test.lua
@@ -1,88 +1,105 @@
import("core.base.global")
-function _write_plugin(dir, name, text)
+-- write a minimal plugin that prints its name when run
+function _write_plugin(dir, name)
io.writefile(path.join(dir, "xmake.lua"), string.format([[
task("%s")
set_category("plugin")
on_run("main")
- set_menu {usage = "xmake %s"}
-]], name, name))
- io.writefile(path.join(dir, "main.lua"), string.format([[function main() print("%s") end]], text))
+ set_menu {usage = "xmake %s", description = "say hello from %s"}
+]], name, name, name))
+ io.writefile(path.join(dir, "main.lua"), string.format([[function main() print("%s") end]], name))
end
-function main(t)
+-- create a temporary plugin repository (packages layout: plugins/<first-letter>/<name>) and register it
+--
+-- @return reponame, names, cleanup
+function _mock_repo(basenames)
local suffix = path.filename(os.tmpfile()):gsub("[^%w]", "")
- local reponame = "plugin-test-repository-" .. suffix
- local hello_name = "plugin-test-hello-" .. suffix
- local formatter_name = "plugin-test-formatter-" .. suffix
- local available_name = "plugin-test-available-" .. suffix
- local local_name = "plugin-test-local-" .. suffix
- local repodir = os.tmpfile() .. ".plugins-repository"
- local localdir = path.join(os.tmpfile() .. ".local-plugin", local_name)
- local plugindir = path.join(global.directory(), "plugins")
+ local reponame = "plugin-test-repo-" .. suffix
+ local repodir = os.tmpfile() .. ".plugin-repo"
+ local names = {}
+ for _, base in ipairs(basenames) do
+ local name = base .. "-" .. suffix
+ _write_plugin(path.join(repodir, "plugins", name:sub(1, 1), name), name)
+ table.insert(names, name)
+ end
+
+ -- register the repository into the cache
local cachefile = path.join(global.cachedir(), "repository")
+ local cache = os.isfile(cachefile) and io.load(cachefile) or {}
+ cache.repositories = cache.repositories or {}
+ cache.repositories[reponame] = {repodir}
+ io.save(cachefile, cache)
- -- reset test state
local function cleanup()
- for _, name in ipairs({hello_name, formatter_name, available_name, local_name}) do
- os.tryrm(path.join(plugindir, name))
+ for _, name in ipairs(names) do
+ os.tryrm(path.join(global.directory(), "plugins", name))
end
local cache = os.isfile(cachefile) and io.load(cachefile) or {}
- cache.repositories = cache.repositories or {}
- cache.repositories[reponame] = nil
+ if cache.repositories then
+ cache.repositories[reponame] = nil
+ end
io.save(cachefile, cache)
os.tryrm(repodir)
- os.tryrm(path.directory(localdir))
end
- cleanup()
+ return reponame, names, cleanup
+end
- -- mock repository with installed and available plugins (packages-like layout: plugins/<first-letter>/<name>)
- _write_plugin(path.join(repodir, "plugins", hello_name:sub(1, 1), hello_name), hello_name, "repo-ok")
- _write_plugin(path.join(repodir, "plugins", formatter_name:sub(1, 1), formatter_name), formatter_name, "format-ok")
- _write_plugin(path.join(repodir, "plugins", available_name:sub(1, 1), available_name), available_name, "available-ok")
- os.mkdir(path.directory(cachefile))
- local cache = os.isfile(cachefile) and io.load(cachefile) or {}
- cache.repositories = cache.repositories or {}
- cache.repositories[reponame] = {repodir}
- io.save(cachefile, cache)
+-- install a plugin 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]
- -- Feature: install by plain name from repository
- os.runv("xmake", {"plugin", "--install", hello_name})
- os.runv("xmake", {hello_name})
+ -- install by plain name (searched across all repositories)
+ os.runv("xmake", {"plugin", "--install", name})
+ t:require(os.iorunv("xmake", {name}):find(name, 1, true))
- -- Feature: install by repo@name format
- os.runv("xmake", {"plugin", "--install", reponame .. "@" .. formatter_name})
- os.runv("xmake", {formatter_name})
+ -- reinstall by repo@name
+ os.runv("xmake", {"plugin", "--remove", name})
+ os.runv("xmake", {"plugin", "--install", reponame .. "@" .. name})
+ t:require(os.iorunv("xmake", {name}):find(name, 1, true))
- -- Feature: --list shows installed and available repository plugins
- local out = os.iorun("xmake plugin --list")
- t:require(out:find("the built-in plugins:", 1, true))
- t:require(out:find("project", 1, true))
- t:require(out:find(hello_name, 1, true))
- t:require(out:find(formatter_name, 1, true))
- t:require(out:find(available_name, 1, true))
- t:require(out:find("xmake plugin --install " .. available_name, 1, true))
+ os.runv("xmake", {"plugin", "--remove", name})
+ cleanup()
+end
+
+-- install a plugin from a local directory, then remove it
+function test_install_from_local(t)
+ local suffix = path.filename(os.tmpfile()):gsub("[^%w]", "")
+ local name = "hello-local-" .. suffix
+ local dir = path.join(os.tmpfile() .. ".plugin-local", name)
+ _write_plugin(dir, name)
- -- Feature: install from local directory
- _write_plugin(localdir, local_name, "local-ok")
- os.runv("xmake", {"plugin", "--install", localdir})
- os.runv("xmake", {local_name})
+ os.runv("xmake", {"plugin", "--install", dir})
+ t:require(os.iorunv("xmake", {name}):find(name, 1, true))
- out = os.iorun("xmake plugin --list")
- t:require(out:find(local_name, 1, true))
+ -- the removed plugin should no longer be runnable
+ os.runv("xmake", {"plugin", "--remove", name})
+ t:require_not(try { function () os.runv("xmake", {name}); return true end })
- -- Feature: remove plugin
- os.runv("xmake", {"plugin", "--remove", local_name})
- out = os.iorun("xmake plugin --list")
- t:require_not(out:find(local_name, 1, true))
+ os.tryrm(path.directory(dir))
+end
- -- Feature: install non-existent plugin fails gracefully
- local ok = try { function () os.runv("xmake", {"plugin", "--install", "plugin-test-missing-" .. suffix}) return true end }
- t:require_not(ok)
+-- --list shows the built-in, installed and available plugins
+function test_list(t)
+ local reponame, names, cleanup = _mock_repo({"hello", "world"})
- -- Feature: reject plugin name traversal
- ok = try { function () os.runv("xmake", {"plugin", "--install", reponame .. "@.."}) return true end }
- t:require_not(ok)
+ -- install the first plugin, leave the second only available
+ os.runv("xmake", {"plugin", "--install", names[1]})
+ local out = os.iorunv("xmake", {"plugin", "--list"})
+ t:require(out:find("the built-in plugins:", 1, true))
+ t:require(out:find("project", 1, true))
+ t:require(out:find(names[1], 1, true))
+ t:require(out:find(names[2], 1, true))
+ t:require(out:find("xmake plugin --install " .. names[2], 1, true))
+ os.runv("xmake", {"plugin", "--remove", names[1]})
cleanup()
end
+
+-- invalid installs should fail
+function test_install_invalid(t)
+ t:require_not(try { function () os.runv("xmake", {"plugin", "--install", "plugin-test-missing"}); return true end })
+ t:require_not(try { function () os.runv("xmake", {"plugin", "--install", "somerepo@.."}); return true end })
+end
diff --git a/xmake/plugins/plugin/main.lua b/xmake/plugins/plugin/main.lua
index 48bae9cde..5158352c0 100644
--- a/xmake/plugins/plugin/main.lua
+++ b/xmake/plugins/plugin/main.lua
@@ -74,17 +74,17 @@ function _install_plugins_from_repo(name, reponame)
raise("plugin(%s): not found in any repository! try ${bright}xrepo update-repo${clear} first.", name)
end
--- install a plugin from a local directory
-function _install_from_local(dir)
+-- install a single plugin from a source directory (as the given name, default to the directory name)
+function _install_from_local(dir, name)
assert(os.isdir(dir) and os.isfile(path.join(dir, "xmake.lua")), "plugin path(%s): ${bright}xmake.lua${clear} not found!", dir)
- local name = path.filename(path.absolute(dir))
+ name = name or path.filename(path.absolute(dir))
local dstdir = _get_plugindir(name)
assert(not os.isdir(dstdir), "plugin(%s) already exists!", name)
os.vcp(dir, dstdir)
- cprint("${color.success}install ${bright}%s${clear} from ${bright}%s${clear} ok!", name, dir)
+ cprint("${color.success}install ${bright}%s${clear} ok!", name)
end
--- install a plugin from a git url or github shortcut
+-- install a single plugin from a git url or github shortcut, e.g. https://github.com/xmake-io/hello-world
function _install_from_git(url)
local branch
if url:startswith("github:") then
@@ -95,9 +95,11 @@ function _install_from_git(url)
end
url = git.asgiturl(url)
end
+ local name = (path.filename(url):gsub("%.git$", ""))
local tmpdir = os.tmpfile() .. ".dir"
git.clone(url, {verbose = option.get("verbose"), branch = branch, outputdir = tmpdir})
- _copy_plugins_from_dir(tmpdir)
+ os.tryrm(path.join(tmpdir, ".git"))
+ _install_from_local(tmpdir, name)
os.tryrm(tmpdir)
end
@@ -131,18 +133,6 @@ function _install_one(name)
_install_plugins_from_repo(name)
end
--- copy every plugin found under the cloned directory into the plugins directory
-function _copy_plugins_from_dir(tmpdir)
- for _, filepath in ipairs(os.files(path.join(tmpdir, "*", "xmake.lua"))) do
- local srcdir = path.directory(filepath)
- local name = path.filename(srcdir)
- local dstdir = _get_plugindir(name)
- assert(not os.isdir(dstdir), "plugin(%s) already exists!", name)
- os.vcp(srcdir, dstdir)
- cprint(" ${color.success}-> ${bright}%s${clear}", name)
- end
-end
-
-- install plugins
function _install()
local names = assert(option.get("plugins"), "please specify the plugins to be installed!")
diff --git a/xmake/plugins/plugin/xmake.lua b/xmake/plugins/plugin/xmake.lua
index 8da06a92e..4aab3daa4 100644
--- a/xmake/plugins/plugin/xmake.lua
+++ b/xmake/plugins/plugin/xmake.lua
@@ -31,13 +31,13 @@ task("plugin")
{'c', "clear", "k", nil, "Clear all installed plugins."},
{nil, "plugins", "vs", nil, "The plugin paths, urls or names.",
"e.g.",
- " $ xmake plugin --install https://github.com/xmake-io/xmake-plugins",
- " $ xmake plugin --install github:xmake-io/xmake-plugins",
- " $ xmake plugin --install github:xmake-io/xmake-plugins#dev",
+ " $ xmake plugin --install https://github.com/myrepo/hello",
+ " $ xmake plugin --install github:myrepo/hello",
+ " $ xmake plugin --install github:myrepo/hello#dev",
" $ xmake plugin --install /tmp/my-plugin",
- " $ xmake plugin --install xmake-repo@hello-world",
- " $ xmake plugin --install hello-world",
- " $ xmake plugin --remove hello-world",
+ " $ xmake plugin --install xmake-repo@hello",
+ " $ xmake plugin --install hello",
+ " $ xmake plugin --remove hello",
" $ xmake plugin --list"}
}
}