Packages

A fork of the original remix package which fixes several errors from the old version, which hasn't been updated since 2016. Original Description: Recompiles mix projects on any change to the lib directory.

Current section

Files

Jump to
remixed_remix lib remix worker.ex
Raw

lib/remix/worker.ex

defmodule RemixedRemix.Worker do
require Logger
use GenServer
def start_link do
GenServer.start_link(__MODULE__, %{}, name: RemixedRemix.Worker)
end
def init(state) do
Process.send_after(__MODULE__, :poll_and_reload, 10000)
{:ok, state}
end
def handle_info(:poll_and_reload, state) do
new_state =
Map.new(paths(), fn path ->
current_mtime = get_current_mtime(path)
last_mtime =
case Map.fetch(state, path) do
{:ok, val} -> val
:error -> nil
end
handle_path(path, current_mtime, last_mtime)
end)
Process.send_after(__MODULE__, :poll_and_reload, 1000)
{:noreply, new_state}
end
def handle_path(path, current_mtime, current_mtime), do: {path, current_mtime}
def handle_path(path, current_mtime, _) do
comp_elixir =
if Mix.Project.umbrella?() do
fn -> Mix.ProjectStack.recur(fn -> recursive_compile() end) end
else
fn -> Mix.Tasks.Compile.Elixir.run(["--ignore-module-conflict"]) end
end
comp_escript = fn -> Mix.Tasks.Escript.Build.run([]) end
case Application.get_all_env(:remixed_remix)[:silent] do
true ->
ExUnit.CaptureIO.capture_io(comp_elixir)
if Application.get_all_env(:remixed_remix)[:escript] == true do
ExUnit.CaptureIO.capture_io(comp_escript)
end
_ ->
comp_elixir.()
if Application.get_all_env(:remixed_remix)[:escript] == true do
comp_escript.()
end
end
{path, current_mtime}
end
def get_current_mtime(dir) do
case File.ls(dir) do
{:ok, files} -> get_current_mtime(files, [], dir)
_ -> nil
end
end
def get_current_mtime([], mtimes, _cwd) do
mtimes
|> Enum.sort()
|> Enum.reverse()
|> List.first()
end
def get_current_mtime([head | tail], mtimes, cwd) do
mtime =
case File.dir?("#{cwd}/#{head}") do
true -> get_current_mtime("#{cwd}/#{head}")
false -> File.stat!("#{cwd}/#{head}").mtime
end
get_current_mtime(tail, [mtime | mtimes], cwd)
end
defp paths, do: Application.get_env(:remixed_remix, :paths, default_paths())
defp default_paths do
if Mix.Project.umbrella?() do
{:ok, apps} = File.ls("apps/")
Enum.map(apps, fn x -> "apps/#{x}/lib" end)
else
["lib"]
end
end
defp recursive_compile do
# Borrowed from Mix.Task with modification
config = Mix.Project.deps_config() |> Keyword.delete(:deps_path)
for %Mix.Dep{app: app, opts: opts} <- Mix.Dep.Umbrella.cached() do
Mix.Project.in_project(app, opts[:path], config,
fn _ -> Mix.Tasks.Compile.Elixir.run(["--ignore-module-conflict"]) end)
end
end
end