summaryrefslogtreecommitdiff
path: root/tests/plugins/repository/test.lua
blob: 7b1619d5e1dd44d2e98873c7b55c2c48eee78db5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
import("core.base.global")

-- 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", description = "say hello from %s"}
]], name, name, name))
    io.writefile(path.join(dir, "main.lua"), string.format([[function main() print("%s") end]], name))
end

-- write a plugin package description, the plugin sources are placed in its `src` directory
--
-- plugins in a repository are described as packages, e.g. <repodir>/plugins/<first-letter>/<name>/xmake.lua
function _write_plugin_package(dir, name)
    io.writefile(path.join(dir, "xmake.lua"), string.format([[
package("%s")
    set_kind("plugin")
    set_description("say hello from %s")
    set_sourcedir(path.join(os.scriptdir(), "src"))
]], name, name))
    _write_plugin(path.join(dir, "src"), name)
end

-- 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-repo-" .. suffix
    local repodir = os.tmpfile() .. ".plugin-repo"
    local names = {}
    for _, base in ipairs(basenames) do
        local name = base .. "-" .. suffix
        _write_plugin_package(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)

    local function cleanup()
        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 {}
        if cache.repositories then
            cache.repositories[reponame] = nil
        end
        io.save(cachefile, cache)
        os.tryrm(repodir)
    end
    return reponame, names, cleanup
end

-- 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]

    -- install by plain name (searched across all repositories)
    os.runv("xmake", {"plugin", "--install", "-y", name})
    t:require(os.iorunv("xmake", {name}):find(name, 1, true))

    -- reinstall by repo@name
    os.runv("xmake", {"plugin", "--remove", name})
    os.runv("xmake", {"plugin", "--install", "-y", reponame .. "@" .. name})
    t:require(os.iorunv("xmake", {name}):find(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)

    os.runv("xmake", {"plugin", "--install", dir})
    t:require(os.iorunv("xmake", {name}):find(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 })

    os.tryrm(path.directory(dir))
end

-- --list shows the built-in, installed and available plugins
function test_list(t)
    local reponame, names, cleanup = _mock_repo({"hello", "world"})

    -- install the first plugin, leave the second only available
    os.runv("xmake", {"plugin", "--install", "-y", 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", "-y", "plugin-test-missing"}); return true end })
    t:require_not(try { function () os.runv("xmake", {"plugin", "--install", "-y", "somerepo@.."}); return true end })
end