/
watcher.ex
60 lines (51 loc) · 2 KB
/
watcher.ex
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
defmodule Phoenix.Endpoint.Watcher do
@moduledoc false
require Logger
def start_link(cmd, args, opts) do
Task.start_link(__MODULE__, :watch, [to_string(cmd), args, opts])
end
def watch(cmd, args, opts) do
merged_opts = Keyword.merge(
[into: IO.stream(:stdio, :line), stderr_to_stdout: true], opts)
:ok = validate(cmd, args, merged_opts)
try do
System.cmd(cmd, args, merged_opts)
catch
:error, :enoent ->
relative = Path.relative_to_cwd(cmd)
Logger.error "Could not start watcher #{inspect relative} from #{inspect cd(merged_opts)}, executable does not exist"
exit(:shutdown)
else
{_, 0} ->
:ok
{_, _} ->
# System.cmd returned a non-zero exit code
# sleep for a couple seconds before exiting to ensure this doesn't
# hit the supervisor's max_restarts / max_seconds limit
Process.sleep(2000)
exit(:watcher_command_error)
end
end
# We specially handle node to make sure we
# provide a good getting started experience.
defp validate("node", [script|_], merged_opts) do
script_path = Path.expand(script, cd(merged_opts))
cond do
!System.find_executable("node") ->
Logger.error "Could not start watcher because \"node\" is not available. Your Phoenix " <>
"application is still running, however assets won't be compiled. " <>
"You may fix this by installing \"node\" and then running \"cd assets && npm install\"."
exit(:shutdown)
not File.exists?(script_path) ->
Logger.error "Could not start node watcher because script #{inspect script_path} does not " <>
"exist. Your Phoenix application is still running, however assets " <>
"won't be compiled. You may fix this by running \"cd assets && npm install\"."
exit(:shutdown)
true -> :ok
end
end
defp validate(_cmd, _args, _opts) do
:ok
end
defp cd(opts), do: opts[:cd] || File.cwd!()
end