defmodule Phoenix.CodeReloader.ChangeDetector do
  use GenServer

  @moduledoc """
  Watches paths for ctime changes and calls MFA
  """

  def start_link(paths, mfa, poll_every_ms \\ 300) do
    GenServer.start_link(__MODULE__, [paths, mfa, poll_every_ms])
  end

  def init([paths, mfa, poll_every_ms]) do
    paths = List.flatten(paths)

    :timer.send_interval(poll_every_ms, :poll)
    {:ok, {paths, mfa, ctimes(paths)}}
  end

  def handle_info(:poll, {paths, {mod, func, args}, ctimes_before} = state) do
    ctimes_now = ctimes(paths)
    if ctimes_now != ctimes_before do
      apply(mod, func, args)
      {:noreply, {paths, {mod, func, args}, ctimes_now}}
    else
      {:noreply, state}
    end
  end

  defp ctimes(paths) do
    paths
    |> Enum.map(&Path.wildcard(&1))
    |> List.flatten
    |> Enum.map(fn path ->
      case File.stat(path) do
        {:ok, stat} -> {stat.ctime, stat.mtime}
        _ -> nil
      end
    end)
  end
end

defmodule Phoenix.CodeReloader.ChangeDetector do
  use GenServer

  @moduledoc """
  Watches paths for ctime changes and calls MFA
  """

  def start_link(paths, mfa, poll_every_ms \\ 300) do
    GenServer.start_link(__MODULE__, [paths, mfa, poll_every_ms])
  end

  def init([paths, mfa, poll_every_ms]) do
    paths = List.flatten(paths)

    :timer.send_interval(poll_every_ms, :poll)
    {:ok, {paths, mfa, ctimes(paths)}}
  end

  def handle_info(:poll, {paths, {mod, func, args}, ctimes_before} = state) do
    ctimes_now = ctimes(paths)
    if ctimes_now != ctimes_before do
      apply(mod, func, args)
      {:noreply, {paths, {mod, func, args}, ctimes_now}}
    else
      {:noreply, state}
    end
  end

  defp ctimes(paths) do
    paths
    |> Enum.map(&Path.wildcard(&1))
    |> List.flatten
    |> Enum.map(fn path ->
      case File.stat(path) do
        {:ok, stat} -> max(stat.ctime, stat.mtime)
        _ -> nil
      end
    end)
  end
end

Use max for ctime/mtime change detection
Use max for ctime/mtime change detection

VictorZeng/phoenix,ugisozols/phoenix,kyledecot/phoenix,phoenixframework/phoenix,paulcsmith/phoenix,henrik/phoenix,romul/phoenix,rafbgarcia/phoenix,evax/phoenix,rafbgarcia/phoenix,phoenixframework/phoenix,ephe-meral/phoenix,hsavit1/phoenix,michalmuskala/phoenix,SmartCasual/phoenix,sdnorm/phoenix,nshafer/phoenix,lono-devices/phoenix,maxnordlund/phoenix,bsmr-erlang/phoenix,Joe-noh/phoenix,eksperimental/phoenix,StevenNunez/phoenix,mitchellhenke/phoenix,hotvulcan/phoenix,pap/phoenix,Ben-Evolently/phoenix,cas27/phoenix,andrewvy/phoenix,nicrioux/phoenix,bsodmike/phoenix,rodrigues/phoenix,ericmj/phoenix,Rumel/phoenix,greyhwndz/phoenix,Gazler/phoenix,omotenko/phoenix_auth,ephe-meral/phoenix,pap/phoenix,KazuCocoa/phoenix,gjaldon/phoenix,keathley/phoenix,yoavlt/phoenix,CD1212/phoenix,andrewvy/phoenix,iStefo/phoenix,manukall/phoenix,dmarkow/phoenix,trarbr/phoenix,thegrubbsian/phoenix,vic/phoenix,0x00evil/phoenix,nshafer/phoenix,wsmoak/phoenix,linearregression/phoenix,DavidAlphaFox/phoenix,stevedomin/phoenix,elliotcm/phoenix,jeffweiss/phoenix,Kosmas/phoenix,nickgartmann/phoenix,lancehalvorsen/phoenix,marcioj/phoenix,evax/phoenix,CultivateHQ/phoenix,optikfluffel/phoenix,seejee/phoenix,justnoxx/phoenix,stevedomin/phoenix,mitchellhenke/phoenix,manukall/phoenix,robomc/phoenix,brucify/phoenix,yonglehou/phoenix,michalmuskala/phoenix,javimolla/phoenix,Smulligan85/phoenix,mschae/phoenix,mschae/phoenix,wsmoak/phoenix,jwarwick/phoenix,Kosmas/phoenix,Dahoon/phoenix,tony612/phoenix,jasond-s/phoenix,0x00evil/phoenix,mobileoverlord/phoenix,eksperimental/phoenix,kholbekj/phoenix,dmarkow/phoenix,korobkov/phoenix,ahmetabdi/phoenix,ybur-yug/phoenix,beni55/phoenix,jamilabreu/phoenix,ybur-yug/phoenix,DavidAlphaFox/phoenix,optikfluffel/phoenix,Joe-noh/phoenix,jamilabreu/phoenix,wicliff/phoenix,CultivateHQ/phoenix,sadiqmmm/phoenix,Fluxuous/phoenix,safi/phoenix,jeffkreeftmeijer/phoenix,bdtomlin/phoenix,stefania11/phoenix,keathley/phoenix,kidaa/phoenix,mvidaurre/phoenix,Gazler/phoenix,seejee/phoenix,rodrigues/phoenix,ericmj/phoenix,milafrerichs/phoenix,iStefo/phoenix,xtity/simple_phoenix,bsmr-erlang/phoenix,iguberman/phoenix,optikfluffel/phoenix,omotenko/phoenix_auth,korobkov/phoenix,rafbgarcia/phoenix,switchflip/phoenix,foxnewsnetwork/phoenix,doron2402/phoenix,Eventacular/phoenix,GabrielNicolasAvellaneda/phoenix,doomspork/phoenix,arthurcolle/phoenix,begleynk/phoenix,nshafer/phoenix,jwarwick/phoenix,scrogson/phoenix,robhurring/phoenix,ACPK/phoenix,vic/phoenix,trarbr/phoenix,JHKennedy4/phoenix,Rumel/phoenix,Smulligan85/phoenix,kevinold/phoenix,gjaldon/phoenix,mobileoverlord/phoenix,lono-devices/phoenix,cas27/phoenix,fbjork/phoenix,daytonn/phoenix,y-yagi/phoenix,jxs/phoenix,lancehalvorsen/phoenix,0x00evil/phoenix,FND/phoenix,mvidaurre/phoenix,esbullington/phoenix-1,phoenixframework/phoenix