summaryrefslogtreecommitdiff
path: root/xmake/plugins/watch/main.lua
blob: 3199918dec3144a45110a681a22de0bea869816b (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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
--!A cross-platform build utility based on Lua
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
--     http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
--
-- Copyright (C) 2015-present, Xmake Open Source Community.
--
-- @author      ruki
-- @file        main.lua
--

-- imports
import("core.base.option")
import("core.base.fwatcher")
import("core.project.config")

-- add watchdir
function _add_watchdir(watchdir, opt)
    opt = opt or {}
    cprint("watching ${bright}%s/%s${clear} ..", watchdir, opt.recursion and "**" or "*")
    fwatcher.add(watchdir, opt)
end

-- add watchdirs
function _add_watchdirs()
    local watchdirs = option.get("watchdirs")
    local plaindirs = option.get("plaindirs")
    if watchdirs or plaindirs then
        if watchdirs then
            for _, watchdir in ipairs(path.splitenv(watchdirs)) do
                for _, dir in ipairs(os.dirs(watchdir)) do
                    _add_watchdir(dir, {recursion = true})
                end
            end
        end
        if plaindirs then
            for _, watchdir in ipairs(path.splitenv(plaindirs)) do
                for _, dir in ipairs(os.dirs(watchdir)) do
                    _add_watchdir(dir)
                end
            end
        end
    elseif os.isfile(os.projectfile()) then
        watchdirs = os.dirs(path.join(os.projectdir(), "*|.*"))
        for _, watchdir in ipairs(watchdirs) do
            local builddir = path.absolute(config.builddir())
            if path.absolute(watchdir) ~= builddir then
                _add_watchdir(watchdir, {recursion = true})
            end
        end
        _add_watchdir(os.projectdir())
    else
        _add_watchdir(watchdir, {recursion = true})
    end
end

-- run command
function _run_command(events)
    try
    {
        function ()
            local commands = option.get("commands")
            local scriptfile = option.get("script")
            local arbitrary = option.get("arbitrary")
            if commands then
                for _, command in ipairs(commands:split(";")) do
                    os.exec(command)
                end
            elseif arbitrary then
                local program = arbitrary[1]
                local argv = #arbitrary > 1 and table.slice(arbitrary, 2) or {}
                os.execv(program, argv)
            elseif scriptfile and os.isfile(scriptfile) and path.extension(scriptfile) == ".lua" then
                local script = import(path.basename(scriptfile),
                    {rootdir = path.directory(scriptfile), anonymous = true})
                script(events)
            elseif os.isfile(os.projectfile()) then
                local argv = {"build", "-y"}
                if option.get("verbose") then
                    table.insert(argv, "-v")
                end
                if option.get("diagnosis") then
                    table.insert(argv, "-D")
                end
                local target = option.get("target")
                if target then
                    table.insert(argv, target)
                end
                os.execv(os.programfile(), argv)
                if option.get("run") then
                    argv[1] = "run"
                    os.execv(os.programfile(), argv)
                end
            end
        end,
        catch
        {
            function (errors)
                cprint(tostring(errors))
            end
        }
    }
end

function main()

    -- add watchdirs
    _add_watchdirs()

    -- do watch
    local count = 0
    local events = {}
    while true do
        local ok, event = fwatcher.wait(300)
        if ok > 0 then
            local status
            if event.type == fwatcher.ET_CREATE then
                status = "created"
            elseif event.type == fwatcher.ET_MODIFY then
                status = "modified"
            elseif event.type == fwatcher.ET_DELETE then
                status = "deleted"
            end
            print(event.path, status)
            -- we use map to remove repeat events
            events[event.path .. tostring(event.type)] = event
            count = count + 1
        elseif count > 0 then
            _run_command(table.values(events))
            count = 0
        end
    end
end