defmodule OauthMockServer.CodeReloader do
@moduledoc "Hot reloading of code in the lib folder"
use GenServer
require Logger
alias Mix.Tasks.Compile.Elixir, as: ExCompile
def start_link do
Process.send_after(__MODULE__, :poll_and_reload, 5000)
GenServer.start_link(__MODULE__, %{}, name: OauthMockServer.CodeReloader)
end
def init(args), do: {:ok, args}
def handle_info(:poll_and_reload, state) do
current_mtime = get_current_mtime("lib")
handle_path("lib", current_mtime, state)
Process.send_after(__MODULE__, :poll_and_reload, 3000)
{:noreply, current_mtime}
end
def handle_info(_msg, state), do: {:noreply, state}
defp handle_path(path, current_mtime, current_mtime), do: {path, current_mtime}
defp handle_path(path, current_mtime, _) do
Logger.info("Files changed on disk. Recompiling...")
ExCompile.run(["--ignore-module-conflict"])
{path, current_mtime}
end
defp get_current_mtime(dir) do
case File.ls(dir) do
{:ok, files} -> get_current_mtime(files, [], dir)
_ -> nil
end
end
defp get_current_mtime([], mtimes, _cwd) do
mtimes |> Enum.sort() |> Enum.reverse() |> List.first()
end
defp get_current_mtime([h | tail], mtimes, cwd) do
mtime =
case File.dir?("#{cwd}/#{h}") do
true -> get_current_mtime("#{cwd}/#{h}")
false -> File.stat!("#{cwd}/#{h}").mtime
end
get_current_mtime(tail, [mtime | mtimes], cwd)
end
end