Remove hanging callback for

Remove hanging callback for

defmodule Top.Server do
  use GenServer
  @big_dirty_regex ~r/.*:\s(?<total_processes>\d*)\s.*,\s(?<running_processes>\d*).*,\s(?<stuck_processes>\d*).*,\s(?<sleeping_processes>\d*)\s.*,\s(?<threads>\d*).*\n(?<date>\d*\/\d*\/\d*)\s(?<time>\d*:\d*:\d*)\n.*:\s(?<1m_load_avg>\d*\.\d*),\s(?<5m_load_avg>\d*\.\d*),\s(?<15m_load_avg>\d*\.\d*).*\n.*:\s(?<user_cpu_usage>\d*\.\d*).*,\s(?<system_cpu_usage>\d*\.\d*).*,\s(?<idle_cpu>\d*\.\d*).*\n.*:\s(?<resident_sharedlibs>\d*\w)\s.*,\s(?<data_sharedlibs>\d*\w)\s.*,\s(?<linkedit_sharedlibs>\d*\w).*\n.*:\s(?<total_memregions>\d*)\s.*,\s(?<resident_memregions>\d*\w)\s.*,\s(?<private_memregions>\d*\w)\s.*,\s(?<shared_memregions>\d*\w).*\n.*:\s(?<used_physmem>\d*\w)\s.*\s\((?<used_wired_physmem>\d*\w)\s.*\),\s(?<unused_physmem>\d*\w).*\n.*\s(?<v_size>\d*\w)\s.*\s(?<framework_vsize>\d*\w)\s.*\s.*,\s(?<swapins>\d*\(\d*\))\s.*,\s(?<swapouts>\d*\(\d*\)).*\n.*:\s(?<packets_in>\d*\/\d*\w).*.\s(?<packets_out>\d*\/\d*\w).*\n.*:\s(?<read_disks>\d*\/\d*\w).*,\s(?<written_disks>\d*\/\d*\w)\s.*/

  ## Interface
  def start_link(_) do
      GenServer.start_link(__MODULE__, nil, name: :top_server)
  end

  def report, do: GenServer.call(:top_server, {:report})

  def report(key), do: GenServer.call(:top_server, {:report, key})

  ## GenServer Implementation
  def init(_) do
    port = Port.open({:spawn, "top -n 0"}, [:binary])
    {:ok, {Map.new, port}}
  end

  def handle_call({:report}, _, {map, _port} = state) do
    {:reply, map, state}
  end

  def handle_call({:report, key}, _, {map, _port} = state) do
    value = Map.get(map, key)
    {:reply, value, state}
  end

  def handle_info({port, {:data, payload}}, {_old_state, port}) do
    new_state = Regex.named_captures(@big_dirty_regex, payload)
    {:noreply, {new_state, port}}
  end

  def handle_info(_, state), do: {:noreply, state}

  ## Helper/Private Functions
end

defmodule Top.Server do
  use GenServer
  @big_dirty_regex ~r/.*:\s(?<total_processes>\d*)\s.*,\s(?<running_processes>\d*).*,\s(?<stuck_processes>\d*).*,\s(?<sleeping_processes>\d*)\s.*,\s(?<threads>\d*).*\n(?<date>\d*\/\d*\/\d*)\s(?<time>\d*:\d*:\d*)\n.*:\s(?<1m_load_avg>\d*\.\d*),\s(?<5m_load_avg>\d*\.\d*),\s(?<15m_load_avg>\d*\.\d*).*\n.*:\s(?<user_cpu_usage>\d*\.\d*).*,\s(?<system_cpu_usage>\d*\.\d*).*,\s(?<idle_cpu>\d*\.\d*).*\n.*:\s(?<resident_sharedlibs>\d*\w)\s.*,\s(?<data_sharedlibs>\d*\w)\s.*,\s(?<linkedit_sharedlibs>\d*\w).*\n.*:\s(?<total_memregions>\d*)\s.*,\s(?<resident_memregions>\d*\w)\s.*,\s(?<private_memregions>\d*\w)\s.*,\s(?<shared_memregions>\d*\w).*\n.*:\s(?<used_physmem>\d*\w)\s.*\s\((?<used_wired_physmem>\d*\w)\s.*\),\s(?<unused_physmem>\d*\w).*\n.*\s(?<v_size>\d*\w)\s.*\s(?<framework_vsize>\d*\w)\s.*\s.*,\s(?<swapins>\d*\(\d*\))\s.*,\s(?<swapouts>\d*\(\d*\)).*\n.*:\s(?<packets_in>\d*\/\d*\w).*.\s(?<packets_out>\d*\/\d*\w).*\n.*:\s(?<read_disks>\d*\/\d*\w).*,\s(?<written_disks>\d*\/\d*\w)\s.*/

  ## Interface
  def start_link(_) do
      GenServer.start_link(__MODULE__, nil, name: :top_server)
  end

  def report, do: GenServer.call(:top_server, {:report})

  def report(key), do: GenServer.call(:top_server, {:report, key})

  ## GenServer Implementation
  def init(_) do
    port = Port.open({:spawn, "top -n 0"}, [:binary])
    {:ok, {Map.new, port}}
  end

  def handle_call({:report}, _, {map, _port} = state) do
    {:reply, map, state}
  end

  def handle_call({:report, key}, _, {map, _port} = state) do
    value = Map.get(map, key)
    {:reply, value, state}
  end

  def handle_call({:resume}, _, _state) do
    init(nil)
  end

  def handle_info({port, {:data, payload}}, {_old_state, port}) do
    new_state = Regex.named_captures(@big_dirty_regex, payload)
    {:noreply, {new_state, port}}
  end

  def handle_info(_, state), do: {:noreply, state}

  ## Helper/Private Functions
end


Refactor AnswerController test

Refactor AnswerController test

defmodule OntagCoreWeb.AnswerControllerTest do
  use OntagCoreWeb.ConnCase
  alias OntagCore.Guardian

  setup do
    user = create_test_user()
    {:ok, token, _} = Guardian.encode_and_sign(user)

    valid_token =
      build_conn()
      |> put_req_header("authorization", "Bearer #{token}")

    author = create_test_qams_author(user)
    entry = create_test_entry()
    tag = create_test_tag(author)
    question = create_test_question(author)
    annotation = create_test_annotation(author, entry, tag)

    world = %{
      valid_token: valid_token,
      question: question,
      annotation: annotation
    }

    {:ok, world}
  end

  test "POST /answers with wrong parameters", %{valid_token: conn} do
    conn = post(conn, answer_path(build_conn(), :create, %{}))
    assert json_response(conn, :bad_request)
  end

  test "POST /answers with right parameters", %{valid_token: conn,
                                                annotation: annotation,
                                                question: question} do
    params = %{
      question_id: question.id,
      annotations: [annotation.id]
    }

    conn = post(conn, answer_path(build_conn(), :create, params))
    assert json_response(conn, :created)
  end
end

defmodule OntagCoreWeb.AnswerControllerTest do
  use OntagCoreWeb.ConnCase
  alias OntagCore.{QAMS,
                   Accounts,
                   Guardian}

  test "POST /answers without a valid authorization header" do
    conn =
      build_conn()
      |> put_req_header("authorization", "none")
      |> post(answer_path(build_conn(), :create, %{}))

    assert json_response(conn, :unauthorized)
  end

  test "POST /answers with a non-valid token" do
    conn =
      build_conn()
      |> put_req_header("authorization", "Bearer none")
      |> post(answer_path(build_conn(), :create, %{}))

    assert json_response(conn, :unauthorized)
  end

  test "POST /answers with wrong parameters" do
    {:ok, user} = Accounts.create_user(%{username: "john"})
    {:ok, token, _} = Guardian.encode_and_sign(user)

    conn =
      build_conn()
      |> put_req_header("authorization", "Bearer #{token}")
      |> post(answer_path(build_conn(), :create, %{}))

    assert json_response(conn, :bad_request)
  end

  test "POST /answers with right parameters" do
    {:ok, user} = Accounts.create_user(%{username: "john"})
    {:ok, token, _} = Guardian.encode_and_sign(user)
    cms_author = OntagCore.CMS.ensure_author_exists(user)
    {:ok, entry} = OntagCore.CMS.create_entry(cms_author, %{title: "Example entry"})
    qams_author = QAMS.ensure_author_exists(user)
    {:ok, tag1} = QAMS.create_tag(qams_author, %{title: "Tag 1"})
    {:ok, q1} = QAMS.create_question(qams_author, %{title: "Tag 1"})

    annotations_params = %{
      tag_id: tag1.id,
      entry_id: entry.id,
      target: %{something: ""}
    }
    {:ok, a1} = QAMS.create_annotation(qams_author, annotations_params)
    {:ok, a2} = QAMS.create_annotation(qams_author, annotations_params)

    answer_params = %{
      question_id: q1.id,
      annotations: [a1.id, a2.id]
    }

    conn =
      build_conn()
      |> put_req_header("authorization", "Bearer #{token}")
      |> post(answer_path(build_conn(), :create, answer_params))

    assert json_response(conn, :created)
  end
end


update runtime config to support multiple source blockchains and default chain

defmodule Glasnost.RuntimeConfig do
  use GenServer
  require Logger
  @process_name :runtime_config
  @mix_env Mix.env

  def start_link(args \\ %{}, options \\ []) do
     GenServer.start_link(__MODULE__, args, options)
  end

  def init(args) do
     :timer.apply_after(1_000, __MODULE__, :update, [""])
     args = Map.put_new(args, :config, %{})
     {:ok, args}
  end

  def handle_call({:update_config, url}, _from, state) do
    Logger.info("Starting config update...")
    {result, state} = case fetch_external_config(url) do
        {:ok, data} ->
          GenServer.cast(self(), :restart_orchestrator)
          {{:ok, data}, put_in(state, [:config], data)}
        {:error, reason } ->
          {{:error, reason}, state}
    end
    Logger.info("Finishing config update...")
    {:reply, result, state}
  end

  def handle_call(:get_config, _from, state), do: {:reply, state.config, state}

  def handle_call(:exists, _from, state), do: {:reply, state.config != %{}, state}

  def handle_cast(:restart_orchestrator, state) do
    spawn_link(fn ->
      :ok = Supervisor.terminate_child(Glasnost.Supervisor, Glasnost.Orchestrator.AuthorSyncSup)
      {:ok, _} = Supervisor.restart_child(Glasnost.Supervisor, Glasnost.Orchestrator.AuthorSyncSup)
    end)
    {:noreply, state}
  end

  def exists?, do: GenServer.call(@process_name, :exists)

  def get_cached_config(), do: GenServer.call(@process_name, :get_config)

  def update(url), do: GenServer.call(@process_name, {:update_config, url})

  def get(:author_account_names) do
    get_cached_config()
      |> Map.get(:authors)
      |> Enum.map(& &1.account_name)
  end

  def get(key) when is_atom(key) do
     Map.get(get_cached_config(), key) || throw("#{key} is NOT present in the remote config")
  end

  def blog_author, do: get(:blog_author)

  def about_blog_permlink, do: get(:about_blog_permlink)

  def blockchain_client_mod(source_blockchain) do
    case source_blockchain do
      "golos" -> Golos
      "steem" -> Steemex
    end
  end

  def language do
    case get(:language) do
      "russian" -> "ru"
      "english" -> "en"
    end
  end

  def fetch_external_config(url) do
    case @mix_env do
      :dev ->
        config = File.read!("priv/glasnost-dev-config.json") |> Poison.Parser.parse!()
        {:ok, AtomicMap.convert(config, safe: false)}
      :test ->
        config = File.read!("priv/glasnost-test-config.json") |> Poison.Parser.parse!()
        {:ok, AtomicMap.convert(config, safe: false)}
      :prod ->
        with {:ok, %HTTPoison.Response{body: body}} <- HTTPoison.get(url),
          {:ok, config} <- Poison.Parser.parse(body)
        do
          {:ok, AtomicMap.convert(config, safe: false)}
        else
          {:error, reason} -> {:error, reason}
        end
    end
  end

end

defmodule Glasnost.RuntimeConfig do
  use GenServer
  require Logger
  @process_name :runtime_config
  @mix_env Mix.env

  def start_link(args \\ %{}, options \\ []) do
     GenServer.start_link(__MODULE__, args, options)
  end

  def init(args) do
     args = Map.put_new(args, :config, %{})
     {:ok, args}
  end

  def handle_call({:update_config, url}, _from, state) do
    Logger.info("Starting config update...")
      {result, state} = case fetch_external_config(url) do
          {:ok, data} ->
            GenServer.cast(self(), :restart_orchestrator)
            {{:ok, data}, put_in(state, [:config], data)}
          {:error, reason } ->
            {{:error, reason}, state}
      end
    Logger.info("Finishing config update...")
    {:reply, result, state}
  end

  def handle_call(:get_config, _from, state), do: {:reply, state.config, state}

  def handle_call(:exists, _from, state), do: {:reply, state.config != %{}, state}

  def handle_cast(:restart_orchestrator, state) do
    spawn_link(fn ->
      :ok = Supervisor.terminate_child(Glasnost.Supervisor, Glasnost.Orchestrator.AuthorSyncSup)
      {:ok, _} = Supervisor.restart_child(Glasnost.Supervisor, Glasnost.Orchestrator.AuthorSyncSup)
    end)
    {:noreply, state}
  end

  def exists?, do: GenServer.call(@process_name, :exists)

  def get_cached_config(), do: GenServer.call(@process_name, :get_config)

  def update(url), do: GenServer.call(@process_name, {:update_config, url})

  def get(:author_account_names) do
    get_cached_config()
      |> Map.get(:authors)
      |> Enum.map(& &1.account_name)
  end

  def get(key) when is_atom(key) do
     Map.get(get_cached_config(), key) || throw("#{key} is NOT present in the remote config")
  end

  def blog_author, do: get(:blog_author)

  def source_blockchain, do: get(:source_blockchain)

  def about_blog_permlink, do: get(:about_blog_permlink)

  def blockchain_client_mod() do
    case String.downcase(source_blockchain()) do
      "golos" -> Golos
      "steem" -> Steemex
    end
  end

  def language do
    case source_blockchain() do
      "golos" -> "ru"
      "steem" -> "en"
    end
  end

  def fetch_external_config(url) do
    case @mix_env do
      :dev ->
        config = File.read!("priv/glasnost-dev-config.json") |> Poison.Parser.parse!()
        {:ok, AtomicMap.convert(config, safe: false)}
      :test ->
        config = File.read!("priv/glasnost-test-config.json") |> Poison.Parser.parse!()
        {:ok, AtomicMap.convert(config, safe: false)}
      :prod ->
        with {:ok, %HTTPoison.Response{body: body}} <- HTTPoison.get(url),
          {:ok, config} <- Poison.Parser.parse(body)
        do
          {:ok, AtomicMap.convert(config, safe: false)}
        else
          {:error, reason} -> {:error, reason}
        end
    end
  end

end


Update binary_search_test.exs

Update binary_search_test.exs

removing spaces

if !System.get_env("EXERCISM_TEST_EXAMPLES") do
  Code.load_file("binary_search.exs", __DIR__)
end

ExUnit.start
ExUnit.configure exclude: :pending, trace: true

defmodule BinarySearchTest do
  use ExUnit.Case

  test "returns :not_found on empty tuple" do
    assert BinarySearch.search({}, 2) == :not_found
  end

  @tag :pending
  test "returns :not_found when key is not in the tuple" do
    assert BinarySearch.search({2, 4, 6}, 3) == :not_found
  end

  @tag :pending
  test "returns :not_found when key is too high" do
    assert BinarySearch.search({2, 4, 6}, 9) == :not_found
  end

  @tag :pending
  test "finds key in a tuple with a single item" do
    assert BinarySearch.search({3}, 3) == {:ok, 0}
  end

  @tag :pending
  test "finds key when it is the first element in tuple" do
    assert BinarySearch.search({1, 2, 4, 5, 6}, 1) == {:ok, 0}
  end

  @tag :pending
  test "finds key when it is in the middle of the tuple" do
    assert BinarySearch.search({1, 2, 4, 5, 6}, 4) == {:ok, 2}
  end

  @tag :pending
  test "finds key when it is the last element in tuple" do
    assert BinarySearch.search({1, 2, 4, 5, 6}, 6) == {:ok, 4}
  end

  @tag :pending
  test "finds key in a tuple with an even number of elements" do
    tuple = {1, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377}
    assert BinarySearch.search(tuple, 21) == {:ok, 5}
    assert BinarySearch.search(tuple, 34) == {:ok, 6}
  end
end


Fix converting asset kind to module in Asset.Command

defmodule FarmbotCore.Asset.Command do
  @moduledoc """
  A collection of functions that _write_ to the DB
  """
  alias FarmbotCore.{Asset, Asset.Repo}

  @typedoc "String kind that should be turned into an Elixir module."
  @type kind :: String.t()

  @typedoc "key/value map of changes"
  @type params :: map()

  @typedoc "remote database id"
  @type id :: integer()

  @doc """
  Will insert, update or delete data in the local database.
  This function will raise if error occur.
  """
  @callback update(kind, params, id) :: :ok | no_return()

  def update("Device", params) do
    Asset.update_device!(params)
    :ok
  end

  def update("FbosConfig", params, _) do
    Asset.update_fbos_config!(params)
    :ok
  end

  def update("FirmwareConfig", params, _) do
    Asset.update_firmware_config!(params)
    :ok
  end

  def update("FarmwareEnv", params, id) do
    Asset.upsert_farmware_env_by_id(id, params)
    :ok
  end

  def update("FarmwareInstallation", id, params) do
    Asset.upsert_farmware_env_by_id(id, params)
    :ok
  end

  # Deletion use case:
  def update(asset_kind, nil, id) do
    old = Repo.get_by(as_module!(asset_kind), id: id)
    old && Repo.delete!(old)
    :ok
  end

  # Catch-all use case:
  def update(asset_kind, params, id) do
    mod = as_module!(asset_kind)
    case Repo.get_by(mod, id: id) do
      nil ->
        struct!(mod)
        |> mod.changeset(params)
        |> Repo.insert!()

      asset ->
        mod.changeset(asset, params)
        |> Repo.update!()
    end

    :ok
  end

  @doc "Returns a Ecto Changeset that can be cached or applied."
  @callback new_changeset(kind, id, params) :: Ecto.Changeset.t()
  def new_changeset(asset_kind, id, params) do
    mod = as_module!(asset_kind)
    asset = Repo.get_by(mod, id: id) || struct!(mod)
    mod.changeset(asset, params)
  end

  defp as_module!("Device"), do: Asset.Device
  defp as_module!("DiagnosticDump"), do: Asset.DiagnosticDump
  defp as_module!("FarmEvent"), do: Asset.FarmEvent
  defp as_module!("FarmwareEnv"), do: Asset.FarmwareEnv
  defp as_module!("FarmwareInstallation"), do: Asset.FarmwareInstallation
  defp as_module!("FbosConfig"), do: Asset.FbosConfig
  defp as_module!("FirmwareConfig"), do: Asset.FirmwareConfig
  defp as_module!("Peripheral"), do: Asset.Peripheral
  defp as_module!("PinBinding"), do: Asset.PinBinding
  defp as_module!("Point"), do: Asset.Point
  defp as_module!("Regimen"), do: Asset.Regimen
  defp as_module!("Sensor"), do: Asset.Sensor
  defp as_module!("Sequence"), do: Asset.Sequence
  defp as_module!("Tool"), do: Asset.Tool
  defp as_module!(kind) when is_binary(kind) do
    raise("""
    Unknown kind: #{kind}
    """)
  end
end

defmodule FarmbotCore.Asset.Command do
  @moduledoc """
  A collection of functions that _write_ to the DB
  """
  alias FarmbotCore.{Asset, Asset.Repo}

  @typedoc "String kind that should be turned into an Elixir module."
  @type kind :: String.t()

  @typedoc "key/value map of changes"
  @type params :: map()

  @typedoc "remote database id"
  @type id :: integer()

  @doc """
  Will insert, update or delete data in the local database.
  This function will raise if error occur.
  """
  @callback update(kind, params, id) :: :ok | no_return()

  def update("Device", params) do
    Asset.update_device!(params)
    :ok
  end

  def update("FbosConfig", params, _) do
    Asset.update_fbos_config!(params)
    :ok
  end

  def update("FirmwareConfig", params, _) do
    Asset.update_firmware_config!(params)
    :ok
  end

  def update("FarmwareEnv", params, id) do
    Asset.upsert_farmware_env_by_id(id, params)
    :ok
  end

  def update("FarmwareInstallation", id, params) do
    Asset.upsert_farmware_env_by_id(id, params)
    :ok
  end

  # Deletion use case:
  def update(asset_kind, nil, id) do
    old = Repo.get_by(as_module(asset_kind), id: id)
    old && Repo.delete!(old)
    :ok
  end

  # Catch-all use case:
  def update(asset_kind, params, id) do
    case Repo.get_by(as_module(asset_kind), id: id) do
      nil ->
        struct!(asset_kind)
        |> asset_kind.changeset(params)
        |> Repo.insert!()

      asset ->
        asset_kind.changeset(asset, params)
        |> Repo.update!()
    end

    :ok
  end

  @doc "Returns a Ecto Changeset that can be cached or applied."
  @callback new_changeset(kind, id, params) :: Ecto.Changeset.t()
  def new_changeset(asset_kind, id, params) do
    mod = as_module(asset_kind)
    asset = Repo.get_by(mod, id: id) || struct!(asset_kind)
    mod.changeset(asset, params)
  end

  defp as_module("Device"), do: Asset.Device
  defp as_module("DiagnosticDump"), do: Asset.DiagnosticDump
  defp as_module("FarmEvent"), do: Asset.FarmEvent
  defp as_module("FarmwareEnv"), do: Asset.FarmwareEnv
  defp as_module("FarmwareInstallation"), do: Asset.FarmwareInstallation
  defp as_module("FbosConfig"), do: Asset.FbosConfig
  defp as_module("FirmwareConfig"), do: Asset.FirmwareConfig
  defp as_module("Peripheral"), do: Asset.Peripheral
  defp as_module("PinBinding"), do: Asset.PinBinding
  defp as_module("Point"), do: Asset.Point
  defp as_module("Regimen"), do: Asset.Regimen
  defp as_module("Sensor"), do: Asset.Sensor
  defp as_module("Sequence"), do: Asset.Sequence
  defp as_module("Tool"), do: Asset.Tool
  defp as_module(kind) when is_binary(kind) do
    raise("""
    Unknown kind: #{kind}
    """)
  end
end


final change

final change

defmodule Core.OsdiController do
  use Core.Web, :controller

  def signup(conn, signup_body = %{"person" => %{}}) do
    response =
      signup_body
      |> to_atom_map()
      |> Osdi.PersonSignup.main()
      |> do_remove_tags(signup_body)

    json conn, response
  end

  def record_contact(conn, record_contact_body = %{"contact" => %{}}) do
    as_atom_map = to_atom_map(record_contact_body)
    {:ok, action_date, _} = DateTime.from_iso8601(as_atom_map.contact.action_date)

    response =
      as_atom_map
      |> put_in([:contact, :action_date], action_date)
      |> Osdi.RecordContact.main()

    json conn, Map.take(response, ~w(action_date contact_effort_id contact_type origin_system status_code target_id success identifiers contactor_id)a)
  end

  defp do_remove_tags(person, %{"remove_tags" => tags_to_remove}), do:
    Osdi.Person.remove_tags(person, tags_to_remove)

  defp do_remove_tags(person, %{}), do: person

  defp to_atom_map(map) when is_map(map), do: Map.new(map, fn {k, v} -> {String.to_atom(k), to_atom_map(v)} end)
  defp to_atom_map(v) when is_list(v), do: Enum.map(v, &to_atom_map/1)
  defp to_atom_map(v), do: v
end

defmodule Core.OsdiController do
  use Core.Web, :controller

  def signup(conn, signup_body = %{"person" => %{}}) do
    response =
      signup_body
      |> to_atom_map()
      |> Osdi.PersonSignup.main()
      |> do_remove_tags(signup_body)

    json conn, response
  end

  def record_contact(conn, record_contact_body = %{"contact" => %{}}) do
    as_atom_map = to_atom_map(record_contact_body)
    {:ok, action_date, _} = DateTime.from_iso8601(as_atom_map.contact.action_date)

    response =
      as_atom_map
      |> Map.put(:action_date, action_date)
      |> Osdi.RecordContact.main()

    json conn, Map.take(response, ~w(action_date contact_effort_id contact_type origin_system status_code target_id success identifiers contactor_id)a)
  end

  defp do_remove_tags(person, %{"remove_tags" => tags_to_remove}), do:
    Osdi.Person.remove_tags(person, tags_to_remove)

  defp do_remove_tags(person, %{}), do: person

  defp to_atom_map(map) when is_map(map), do: Map.new(map, fn {k, v} -> {String.to_atom(k), to_atom_map(v)} end)
  defp to_atom_map(v) when is_list(v), do: Enum.map(v, &to_atom_map/1)
  defp to_atom_map(v), do: v
end


height bug

height bug

defmodule NeoscanSync.FastSync do
  @moduledoc false

  @moduledoc """

    External process to fetch blockchain from RCP node sync, and print json

  """

  alias NeoscanSync.Blockchain
  alias Neoscan.Pool
  alias NeoscanSync.BlockSync

  @me __MODULE__

  #Starts the application
  def start_link() do
    Agent.start_link(fn -> start() end , name: @me)
  end

  #Start process, create file and get current height from the chain
  def start(n \\ 500) do
    count = Pool.get_highest_block_in_pool()
    fetch_chain(n, count)
  end

  def check_process() do
    alive = Process.whereis(Neoscan.Supervisor)
    |> Process.alive?
    case alive do
      true ->
        true
      false ->
        IO.puts("Main process was killed")
        Process.exit(self(), :shutdown)
    end
  end

  def fetch_chain(n, count) do
    check_process()
    get_current_height()
    |> evaluate(n, count+1)
  end

  #evaluate number of process, current block count, and start async functions
  defp evaluate(result, n, count) do
    case result do
      {:ok, height} when (height) > count  ->
        cond do
          height  - count >= n ->
            Enum.to_list(count..(count+n-1))
            |> Enum.map(&Task.async(fn -> cross_check(&1) end))
            |> Enum.map(&Task.await(&1, 20000))
            |> Enum.map(fn x -> add_block(x) end)
            fetch_chain(n, count+n-1)
          height  - count < n ->
            Enum.to_list(count..(height))
            |> Enum.map(&Task.async(fn -> cross_check(&1) end))
            |> Enum.map(&Task.await(&1, 20000))
            |> Enum.map(fn x -> add_block(x) end)
            BlockSync.start()
        end
      {:ok, height} when (height) == count  ->
        BlockSync.start()
      {:ok, height} when (height) < count  ->
        start(n)
    end
  end

  #write block to the file
  def add_block(%{"index" => num} = block) do
    %{"height" => num, "block" => block}
    |> Pool.create_data()
    IO.puts("Block #{num} saved in pool")
  end

  #cross check block hash between different seeds
  def cross_check(height) do
    [random1, random2] = Enum.to_list(0..9) |> Enum.take_random(2)
    blockA = get_block_by_height(random1, height)
    blockB = get_block_by_height(random2, height)
    cond do
      blockA == blockB ->
        blockA
      true ->
        cross_check(height)
    end
  end

  #handles error when fetching block from chain
  def get_block_by_height(random, height) do
    case Blockchain.get_block_by_height(random, height) do
      { :ok , block } ->
        block
      { :error, %{"code" => num}} when num < 0 ->
        get_block_by_height(Enum.random(0..9), height)
      { :error, _reason} ->
        get_block_by_height(random, height)
    end
  end

  #handles error when fetching height from chain
  def get_current_height() do
    case Blockchain.get_current_height() do
      { :ok , height } ->
        { :ok , height }
      { :error, _reason} ->
        get_current_height()
    end
  end

end

defmodule NeoscanSync.FastSync do
  @moduledoc false

  @moduledoc """

    External process to fetch blockchain from RCP node sync, and print json

  """

  alias NeoscanSync.Blockchain
  alias Neoscan.Pool
  alias NeoscanSync.BlockSync

  @me __MODULE__

  #Starts the application
  def start_link() do
    Agent.start_link(fn -> start() end , name: @me)
  end

  #Start process, create file and get current height from the chain
  def start(n \\ 500) do
    count = Pool.get_highest_block_in_pool()
    fetch_chain(n, count)
  end

  def check_process() do
    alive = Process.whereis(Neoscan.Supervisor)
    |> Process.alive?
    case alive do
      true ->
        true
      false ->
        IO.puts("Main process was killed")
        Process.exit(self(), :shutdown)
    end
  end

  def fetch_chain(n, count) do
    check_process()
    get_current_height()
    |> evaluate(n, count+1)
  end

  #evaluate number of process, current block count, and start async functions
  defp evaluate(result, n, count) do
    case result do
      {:ok, height} when (height) > count  ->
        cond do
          height  - count >= n ->
            Enum.to_list(count..(count+n-1))
            |> Enum.map(&Task.async(fn -> cross_check(&1) end))
            |> Enum.map(&Task.await(&1, 20000))
            |> Enum.map(fn x -> add_block(x) end)
            fetch_chain(n, count+n-1)
          height  - count < n ->
            Enum.to_list(count..(height))
            |> Enum.map(&Task.async(fn -> cross_check(&1) end))
            |> Enum.map(&Task.await(&1, 20000))
            |> Enum.map(fn x -> add_block(x) end)
            BlockSync.start()
        end
      {:ok, height} when (height) == count  ->
        BlockSync.start()
      {:ok, height} when (height) < count  ->
        start(n)
    end
  end

  #write block to the file
  def add_block(%{"index" => num} = block) do
    %{"height" => num, "block" => block}
    |> Pool.create_data()
    IO.puts("Block #{num} saved in pool")
  end

  #cross check block hash between different seeds
  def cross_check(height) do
    [random1, random2] = Enum.to_list(0..9) |> Enum.take_random(2)
    blockA = get_block_by_height(random1, height)
    blockB = get_block_by_height(random2, height)
    cond do
      blockA == blockB ->
        blockA
      true ->
        cross_check(height)
    end
  end

  #handles error when fetching block from chain
  def get_block_by_height(random, height) do
    case Blockchain.get_block_by_height(random, height) do
      { :ok , block } ->
        block
      { :error, %{"code" => num}} when num < 0 ->
        get_block_by_height(Enum.random(0..9), height)
      { :error, _reason} ->
        get_block_by_height(random, height)
    end
  end

  #handles error when fetching height from chain
  def get_current_height() do
    case Blockchain.get_current_height() do
      { :ok , height } ->
        #{ :ok , height }
        { :ok , 6000 }
      { :error, _reason} ->
        get_current_height()
    end
  end

end


Translate all instruments in XML

Translate all instruments in XML

defmodule JumubaseWeb.XMLEncoder do
  @moduledoc """
  A tool to export data as XML for use in other Jumu software,
  most notably JMDaten.
  """

  alias Jumubase.Showtime.{Appearance, Instruments, Performance}

  @doc """
  Encodes the list of performances to XML.
  """
  def encode(performances) do
    {:jumu, nil, Enum.map(performances, &to_xml/1)} |> XmlBuilder.generate
  end

  # Private helpers

  defp to_xml(%Performance{contest_category: cc} = performance) do
    [a1 | rest] = performance.appearances
    {:teilnehmer, %{id: a1.participant.id}, [
      to_xml(a1),
      {:wertung, nil, [
        {:type, nil, map_type(cc.category.type)},
        {:instrument_stimmlage, nil, Instruments.name(a1.instrument)},
      ]},
      {:spielpartner, nil, Enum.map(rest, &{:partner, %{id: &1.participant.id}, to_xml(&1)})}
    ]}
  end
  defp to_xml(%Appearance{participant: p} = a) do
    [
      {:vorname, nil, p.given_name},
      {:nachname, nil, p.family_name},
      {:geburtstag, nil, format_date(p.birthdate)},
      {:tel, nil, p.phone},
      {:email, nil, p.email},
      {:instrument, nil, Instruments.name(a.instrument)},
    ]
  end

  defp map_type("solo"), do: "solo"
  defp map_type("ensemble"), do: "gruppe"

  defp format_date(date), do: Timex.format!(date, "{D}.{M}.{YYYY}")
end

defmodule JumubaseWeb.XMLEncoder do
  @moduledoc """
  A tool to export data as XML for use in other Jumu software,
  most notably JMDaten.
  """

  alias Jumubase.Showtime.{Appearance, Instruments, Performance}

  @doc """
  Encodes the list of performances to XML.
  """
  def encode(performances) do
    {:jumu, nil, Enum.map(performances, &to_xml/1)} |> XmlBuilder.generate
  end

  # Private helpers

  defp to_xml(%Performance{contest_category: cc} = performance) do
    [a1 | rest] = performance.appearances
    {:teilnehmer, %{id: a1.participant.id}, [
      to_xml(a1),
      {:wertung, nil, [
        {:type, nil, map_type(cc.category.type)},
        {:instrument_stimmlage, nil, a1.instrument},
      ]},
      {:spielpartner, nil, Enum.map(rest, &{:partner, %{id: &1.participant.id}, to_xml(&1)})}
    ]}
  end
  defp to_xml(%Appearance{participant: p} = a) do
    [
      {:vorname, nil, p.given_name},
      {:nachname, nil, p.family_name},
      {:geburtstag, nil, format_date(p.birthdate)},
      {:tel, nil, p.phone},
      {:email, nil, p.email},
      {:instrument, nil, Instruments.name(a.instrument)},
    ]
  end

  defp map_type("solo"), do: "solo"
  defp map_type("ensemble"), do: "gruppe"

  defp format_date(date), do: Timex.format!(date, "{D}.{M}.{YYYY}")
end


fix typo

fix typo

defmodule FarmbotCore.BotStateNG.McuParams do
  @moduledoc false
  alias FarmbotCore.BotStateNG.McuParams
  use Ecto.Schema
  import Ecto.Changeset

  @primary_key false

  embedded_schema do
    field(:param_e_stop_on_mov_err, :float)
    field(:param_mov_nr_retry, :float)
    field(:movement_timeout_x, :float)
    field(:movement_timeout_y, :float)
    field(:movement_timeout_z, :float)
    field(:movement_keep_active_x, :float)
    field(:movement_keep_active_y, :float)
    field(:movement_keep_active_z, :float)
    field(:movement_home_at_boot_x, :float)
    field(:movement_home_at_boot_y, :float)
    field(:movement_home_at_boot_z, :float)
    field(:movement_invert_endpoints_x, :float)
    field(:movement_invert_endpoints_y, :float)
    field(:movement_invert_endpoints_z, :float)
    field(:movement_enable_endpoints_x, :float)
    field(:movement_enable_endpoints_y, :float)
    field(:movement_enable_endpoints_z, :float)
    field(:movement_invert_motor_x, :float)
    field(:movement_invert_motor_y, :float)
    field(:movement_invert_motor_z, :float)
    field(:movement_secondary_motor_x, :float)
    field(:movement_secondary_motor_invert_x, :float)
    field(:movement_steps_acc_dec_x, :float)
    field(:movement_steps_acc_dec_y, :float)
    field(:movement_steps_acc_dec_z, :float)
    field(:movement_stop_at_home_x, :float)
    field(:movement_stop_at_home_y, :float)
    field(:movement_stop_at_home_z, :float)
    field(:movement_home_up_x, :float)
    field(:movement_home_up_y, :float)
    field(:movement_home_up_z, :float)
    field(:movement_step_per_mm_x, :float)
    field(:movement_step_per_mm_y, :float)
    field(:movement_step_per_mm_z, :float)
    field(:movement_min_spd_x, :float)
    field(:movement_min_spd_y, :float)
    field(:movement_min_spd_z, :float)
    field(:movement_home_spd_x, :float)
    field(:movement_home_spd_y, :float)
    field(:movement_home_spd_z, :float)
    field(:movement_max_spd_x, :float)
    field(:movement_max_spd_y, :float)
    field(:movement_max_spd_z, :float)
    field(:movement_invert_2_endpoints_x, :float)
    field(:movement_invert_2_endpoints_y, :float)
    field(:movement_invert_2_endpoints_z, :float)
    field(:movement_motor_current_x, :float)
    field(:movement_motor_current_y, :float)
    field(:movement_motor_current_z, :float)
    field(:movement_stall_sensitivity_x, :float)
    field(:movement_stall_sensitivity_y, :float)
    field(:movement_stall_sensitivity_z, :float)
    field(:movement_microsteps_x, :float)
    field(:movement_microsteps_y, :float)
    field(:movement_microsteps_z, :float)
    field(:encoder_enabled_x, :float)
    field(:encoder_enabled_y, :float)
    field(:encoder_enabled_z, :float)
    field(:encoder_type_x, :float)
    field(:encoder_type_y, :float)
    field(:encoder_type_z, :float)
    field(:encoder_missed_steps_max_x, :float)
    field(:encoder_missed_steps_max_y, :float)
    field(:encoder_missed_steps_max_z, :float)
    field(:encoder_scaling_x, :float)
    field(:encoder_scaling_y, :float)
    field(:encoder_scaling_z, :float)
    field(:encoder_missed_steps_decay_x, :float)
    field(:encoder_missed_steps_decay_y, :float)
    field(:encoder_missed_steps_decay_z, :float)
    field(:encoder_use_for_pos_x, :float)
    field(:encoder_use_for_pos_y, :float)
    field(:encoder_use_for_pos_z, :float)
    field(:encoder_invert_x, :float)
    field(:encoder_invert_y, :float)
    field(:encoder_invert_z, :float)
    field(:movement_axis_nr_steps_x, :float)
    field(:movement_axis_nr_steps_y, :float)
    field(:movement_axis_nr_steps_z, :float)
    field(:movement_stop_at_max_x, :float)
    field(:movement_stop_at_max_y, :float)
    field(:movement_stop_at_max_z, :float)
    field(:pin_guard_1_pin_nr, :float)
    field(:pin_guard_1_time_out, :float)
    field(:pin_guard_1_active_state, :float)
    field(:pin_guard_2_pin_nr, :float)
    field(:pin_guard_2_time_out, :float)
    field(:pin_guard_2_active_state, :float)
    field(:pin_guard_3_pin_nr, :float)
    field(:pin_guard_3_time_out, :float)
    field(:pin_guard_3_active_state, :float)
    field(:pin_guard_4_pin_nr, :float)
    field(:pin_guard_4_time_out, :float)
    field(:pin_guard_4_active_state, :float)
    field(:pin_guard_5_pin_nr, :float)
    field(:pin_guard_5_time_out, :float)
    field(:pin_guard_5_active_state, :float)
  end

  def new() do
    %McuParams{}
    |> changeset(%{})
    |> apply_changes()
  end

  def view(mcu_params) do
    %{
      param_e_stop_on_mov_err: mcu_params.param_e_stop_on_mov_err,
      param_mov_nr_retry: mcu_params.param_mov_nr_retry,
      movement_timeout_x: mcu_params.movement_timeout_x,
      movement_timeout_y: mcu_params.movement_timeout_y,
      movement_timeout_z: mcu_params.movement_timeout_z,
      movement_keep_active_x: mcu_params.movement_keep_active_x,
      movement_keep_active_y: mcu_params.movement_keep_active_y,
      movement_keep_active_z: mcu_params.movement_keep_active_z,
      movement_home_at_boot_x: mcu_params.movement_home_at_boot_x,
      movement_home_at_boot_y: mcu_params.movement_home_at_boot_y,
      movement_home_at_boot_z: mcu_params.movement_home_at_boot_z,
      movement_invert_endpoints_x: mcu_params.movement_invert_endpoints_x,
      movement_invert_endpoints_y: mcu_params.movement_invert_endpoints_y,
      movement_invert_endpoints_z: mcu_params.movement_invert_endpoints_z,
      movement_enable_endpoints_x: mcu_params.movement_enable_endpoints_x,
      movement_enable_endpoints_y: mcu_params.movement_enable_endpoints_y,
      movement_enable_endpoints_z: mcu_params.movement_enable_endpoints_z,
      movement_invert_motor_x: mcu_params.movement_invert_motor_x,
      movement_invert_motor_y: mcu_params.movement_invert_motor_y,
      movement_invert_motor_z: mcu_params.movement_invert_motor_z,
      movement_secondary_motor_x: mcu_params.movement_secondary_motor_x,
      movement_secondary_motor_invert_x: mcu_params.movement_secondary_motor_invert_x,
      movement_steps_acc_dec_x: mcu_params.movement_steps_acc_dec_x,
      movement_steps_acc_dec_y: mcu_params.movement_steps_acc_dec_y,
      movement_steps_acc_dec_z: mcu_params.movement_steps_acc_dec_z,
      movement_stop_at_home_x: mcu_params.movement_stop_at_home_x,
      movement_stop_at_home_y: mcu_params.movement_stop_at_home_y,
      movement_stop_at_home_z: mcu_params.movement_stop_at_home_z,
      movement_home_up_x: mcu_params.movement_home_up_x,
      movement_home_up_y: mcu_params.movement_home_up_y,
      movement_home_up_z: mcu_params.movement_home_up_z,
      movement_step_per_mm_x: mcu_params.movement_step_per_mm_x,
      movement_step_per_mm_y: mcu_params.movement_step_per_mm_y,
      movement_step_per_mm_z: mcu_params.movement_step_per_mm_z,
      movement_min_spd_x: mcu_params.movement_min_spd_x,
      movement_min_spd_y: mcu_params.movement_min_spd_y,
      movement_min_spd_z: mcu_params.movement_min_spd_z,
      movement_home_spd_x: mcu_params.movement_home_spd_x,
      movement_home_spd_y: mcu_params.movement_home_spd_y,
      movement_home_spd_z: mcu_params.movement_home_spd_z,
      movement_max_spd_x: mcu_params.movement_max_spd_x,
      movement_max_spd_y: mcu_params.movement_max_spd_y,
      movement_max_spd_z: mcu_params.movement_max_spd_z,
      movement_invert_2_endpoints_x: mcu_params.movement_invert_2_endpoints_x,
      movement_invert_2_endpoints_y: mcu_params.movement_invert_2_endpoints_y,
      movement_invert_2_endpoints_z: mcu_params.movement_invert_2_endpoints_z,
      movement_motor_current_x: mcu_params.movement_motor_current_x,
      movement_motor_current_y: mcu_params.movement_motor_current_y,
      movement_motor_current_z: mcu_params.movement_motor_current_z,
      movement_stall_sensitivity_x: mcu_params.movement_stall_sensitivity_x,
      movement_stall_sensitivity_y: mcu_params.movement_stall_sensitivity_y,
      movement_stall_sensitivity_z: mcu_params.movement_stall_sensitivity_z,
      movement_microsteps_x: mcu_params.movement_microsteps_x,
      movement_microsteps_y: mcu_params.movement_microsteps_y,
      movement_microsteps_z: mcu_params.movement_microsteps_z,
      encoder_enabled_x: mcu_params.encoder_enabled_x,
      encoder_enabled_y: mcu_params.encoder_enabled_y,
      encoder_enabled_z: mcu_params.encoder_enabled_z,
      encoder_type_x: mcu_params.encoder_type_x,
      encoder_type_y: mcu_params.encoder_type_y,
      encoder_type_z: mcu_params.encoder_type_z,
      encoder_missed_steps_max_x: mcu_params.encoder_missed_steps_max_x,
      encoder_missed_steps_max_y: mcu_params.encoder_missed_steps_max_y,
      encoder_missed_steps_max_z: mcu_params.encoder_missed_steps_max_z,
      encoder_scaling_x: mcu_params.encoder_scaling_x,
      encoder_scaling_y: mcu_params.encoder_scaling_y,
      encoder_scaling_z: mcu_params.encoder_scaling_z,
      encoder_missed_steps_decay_x: mcu_params.encoder_missed_steps_decay_x,
      encoder_missed_steps_decay_y: mcu_params.encoder_missed_steps_decay_y,
      encoder_missed_steps_decay_z: mcu_params.encoder_missed_steps_decay_z,
      encoder_use_for_pos_x: mcu_params.encoder_use_for_pos_x,
      encoder_use_for_pos_y: mcu_params.encoder_use_for_pos_y,
      encoder_use_for_pos_z: mcu_params.encoder_use_for_pos_z,
      encoder_invert_x: mcu_params.encoder_invert_x,
      encoder_invert_y: mcu_params.encoder_invert_y,
      encoder_invert_z: mcu_params.encoder_invert_z,
      movement_axis_nr_steps_x: mcu_params.movement_axis_nr_steps_x,
      movement_axis_nr_steps_y: mcu_params.movement_axis_nr_steps_y,
      movement_axis_nr_steps_z: mcu_params.movement_axis_nr_steps_z,
      movement_stop_at_max_x: mcu_params.movement_stop_at_max_x,
      movement_stop_at_max_y: mcu_params.movement_stop_at_max_y,
      movement_stop_at_max_z: mcu_params.movement_stop_at_max_z,
      pin_guard_1_pin_nr: mcu_params.pin_guard_1_pin_nr,
      pin_guard_1_time_out: mcu_params.pin_guard_1_time_out,
      pin_guard_1_active_state: mcu_params.pin_guard_1_active_state,
      pin_guard_2_pin_nr: mcu_params.pin_guard_2_pin_nr,
      pin_guard_2_time_out: mcu_params.pin_guard_2_time_out,
      pin_guard_2_active_state: mcu_params.pin_guard_2_active_state,
      pin_guard_3_pin_nr: mcu_params.pin_guard_3_pin_nr,
      pin_guard_3_time_out: mcu_params.pin_guard_3_time_out,
      pin_guard_3_active_state: mcu_params.pin_guard_3_active_state,
      pin_guard_4_pin_nr: mcu_params.pin_guard_4_pin_nr,
      pin_guard_4_time_out: mcu_params.pin_guard_4_time_out,
      pin_guard_4_active_state: mcu_params.pin_guard_4_active_state,
      pin_guard_5_pin_nr: mcu_params.pin_guard_5_pin_nr,
      pin_guard_5_time_out: mcu_params.pin_guard_5_time_out,
      pin_guard_5_active_state: mcu_params.pin_guard_5_active_state
    }
  end

  def changeset(mcu_params, params \\ %{}) do
    mcu_params
    |> cast(params, [
      :param_e_stop_on_mov_err,
      :param_mov_nr_retry,
      :movement_timeout_x,
      :movement_timeout_y,
      :movement_timeout_z,
      :movement_keep_active_x,
      :movement_keep_active_y,
      :movement_keep_active_z,
      :movement_home_at_boot_x,
      :movement_home_at_boot_y,
      :movement_home_at_boot_z,
      :movement_invert_endpoints_x,
      :movement_invert_endpoints_y,
      :movement_invert_endpoints_z,
      :movement_enable_endpoints_x,
      :movement_enable_endpoints_y,
      :movement_enable_endpoints_z,
      :movement_invert_motor_x,
      :movement_invert_motor_y,
      :movement_invert_motor_z,
      :movement_secondary_motor_x,
      :movement_secondary_motor_invert_x,
      :movement_steps_acc_dec_x,
      :movement_steps_acc_dec_y,
      :movement_steps_acc_dec_z,
      :movement_stop_at_home_x,
      :movement_stop_at_home_y,
      :movement_stop_at_home_z,
      :movement_home_up_x,
      :movement_home_up_y,
      :movement_home_up_z,
      :movement_step_per_mm_x,
      :movement_step_per_mm_y,
      :movement_step_per_mm_z,
      :movement_min_spd_x,
      :movement_min_spd_y,
      :movement_min_spd_z,
      :movement_home_spd_x,
      :movement_home_spd_y,
      :movement_home_spd_z,
      :movement_max_spd_x,
      :movement_max_spd_y,
      :movement_max_spd_z,
      :movement_invert_2_endpoints_x,
      :movement_invert_2_endpoints_y,
      :movement_invert_2_endpoints_z,
      :movement_motor_current_x,
      :movement_motor_current_y,
      :movement_motor_current_z,
      :movement_stall_sensitivity_x,
      :movement_stall_sensitivity_y,
      :movement_stall_sensitivity_z,
      :movement_microsteps_x,
      :movement_microsteps_y,
      :movement_microsteps_z,
      :encoder_enabled_x,
      :encoder_enabled_y,
      :encoder_enabled_z,
      :encoder_type_x,
      :encoder_type_y,
      :encoder_type_z,
      :encoder_missed_steps_max_x,
      :encoder_missed_steps_max_y,
      :encoder_missed_steps_max_z,
      :encoder_scaling_x,
      :encoder_scaling_y,
      :encoder_scaling_z,
      :encoder_missed_steps_decay_x,
      :encoder_missed_steps_decay_y,
      :encoder_missed_steps_decay_z,
      :encoder_use_for_pos_x,
      :encoder_use_for_pos_y,
      :encoder_use_for_pos_z,
      :encoder_invert_x,
      :encoder_invert_y,
      :encoder_invert_z,
      :movement_axis_nr_steps_x,
      :movement_axis_nr_steps_y,
      :movement_axis_nr_steps_z,
      :movement_stop_at_max_x,
      :movement_stop_at_max_y,
      :movement_stop_at_max_z,
      :pin_guard_1_pin_nr,
      :pin_guard_1_time_out,
      :pin_guard_1_active_state,
      :pin_guard_2_pin_nr,
      :pin_guard_2_time_out,
      :pin_guard_2_active_state,
      :pin_guard_3_pin_nr,
      :pin_guard_3_time_out,
      :pin_guard_3_active_state,
      :pin_guard_4_pin_nr,
      :pin_guard_4_time_out,
      :pin_guard_4_active_state,
      :pin_guard_5_pin_nr,
      :pin_guard_5_time_out,
      :pin_guard_5_active_state
    ])
  end
end

defmodule FarmbotCore.BotStateNG.McuParams do
  @moduledoc false
  alias FarmbotCore.BotStateNG.McuParams
  use Ecto.Schema
  import Ecto.Changeset

  @primary_key false

  embedded_schema do
    field(:param_e_stop_on_mov_err, :float)
    field(:param_mov_nr_retry, :float)
    field(:movement_timeout_x, :float)
    field(:movement_timeout_y, :float)
    field(:movement_timeout_z, :float)
    field(:movement_keep_active_x, :float)
    field(:movement_keep_active_y, :float)
    field(:movement_keep_active_z, :float)
    field(:movement_home_at_boot_x, :float)
    field(:movement_home_at_boot_y, :float)
    field(:movement_home_at_boot_z, :float)
    field(:movement_invert_endpoints_x, :float)
    field(:movement_invert_endpoints_y, :float)
    field(:movement_invert_endpoints_z, :float)
    field(:movement_enable_endpoints_x, :float)
    field(:movement_enable_endpoints_y, :float)
    field(:movement_enable_endpoints_z, :float)
    field(:movement_invert_motor_x, :float)
    field(:movement_invert_motor_y, :float)
    field(:movement_invert_motor_z, :float)
    field(:movement_secondary_motor_x, :float)
    field(:movement_secondary_motor_invert_x, :float)
    field(:movement_steps_acc_dec_x, :float)
    field(:movement_steps_acc_dec_y, :float)
    field(:movement_steps_acc_dec_z, :float)
    field(:movement_stop_at_home_x, :float)
    field(:movement_stop_at_home_y, :float)
    field(:movement_stop_at_home_z, :float)
    field(:movement_home_up_x, :float)
    field(:movement_home_up_y, :float)
    field(:movement_home_up_z, :float)
    field(:movement_step_per_mm_x, :float)
    field(:movement_step_per_mm_y, :float)
    field(:movement_step_per_mm_z, :float)
    field(:movement_min_spd_x, :float)
    field(:movement_min_spd_y, :float)
    field(:movement_min_spd_z, :float)
    field(:movement_home_spd_x, :float)
    field(:movement_home_spd_y, :float)
    field(:movement_home_spd_z, :float)
    field(:movement_max_spd_x, :float)
    field(:movement_max_spd_y, :float)
    field(:movement_max_spd_z, :float)
    field(:movement_invert_2_endpoints_x, :float)
    field(:movement_invert_2_endpoints_y, :float)
    field(:movement_invert_2_endpoints_z, :float)
    field(:movement_motor_current_x, :float)
    field(:movement_motor_current_y, :float)
    field(:movement_motor_current_z, :float)
    field(:movement_stall_sensitivity_x, :float)
    field(:movement_stall_sensitivity_y, :float)
    field(:movement_stall_sensitivity_z, :float)
    field(:movement_microsteps_x, :float)
    field(:movement_microsteps_y, :float)
    field(:movement_microsteps_z, :float)
    field(:encoder_enabled_x, :float)
    field(:encoder_enabled_y, :float)
    field(:encoder_enabled_z, :float)
    field(:encoder_type_x, :float)
    field(:encoder_type_y, :float)
    field(:encoder_type_z, :float)
    field(:encoder_missed_steps_max_x, :float)
    field(:encoder_missed_steps_max_y, :float)
    field(:encoder_missed_steps_max_z, :float)
    field(:encoder_scaling_x, :float)
    field(:encoder_scaling_y, :float)
    field(:encoder_scaling_z, :float)
    field(:encoder_missed_steps_decay_x, :float)
    field(:encoder_missed_steps_decay_y, :float)
    field(:encoder_missed_steps_decay_z, :float)
    field(:encoder_use_for_pos_x, :float)
    field(:encoder_use_for_pos_y, :float)
    field(:encoder_use_for_pos_z, :float)
    field(:encoder_invert_x, :float)
    field(:encoder_invert_y, :float)
    field(:encoder_invert_z, :float)
    field(:movement_axis_nr_steps_x, :float)
    field(:movement_axis_nr_steps_y, :float)
    field(:movement_axis_nr_steps_z, :float)
    field(:movement_stop_at_max_x, :float)
    field(:movement_stop_at_max_y, :float)
    field(:movement_stop_at_max_z, :float)
    field(:pin_guard_1_pin_nr, :float)
    field(:pin_guard_1_time_out, :float)
    field(:pin_guard_1_active_state, :float)
    field(:pin_guard_2_pin_nr, :float)
    field(:pin_guard_2_time_out, :float)
    field(:pin_guard_2_active_state, :float)
    field(:pin_guard_3_pin_nr, :float)
    field(:pin_guard_3_time_out, :float)
    field(:pin_guard_3_active_state, :float)
    field(:pin_guard_4_pin_nr, :float)
    field(:pin_guard_4_time_out, :float)
    field(:pin_guard_4_active_state, :float)
    field(:pin_guard_5_pin_nr, :float)
    field(:pin_guard_5_time_out, :float)
    field(:pin_guard_5_active_state, :float)
  end

  def new() do
    %McuParams{}
    |> changeset(%{})
    |> apply_changes()
  end

  def view(mcu_params) do
    %{
      param_e_stop_on_mov_err: mcu_params.param_e_stop_on_mov_err,
      param_mov_nr_retry: mcu_params.param_mov_nr_retry,
      movement_timeout_x: mcu_params.movement_timeout_x,
      movement_timeout_y: mcu_params.movement_timeout_y,
      movement_timeout_z: mcu_params.movement_timeout_z,
      movement_keep_active_x: mcu_params.movement_keep_active_x,
      movement_keep_active_y: mcu_params.movement_keep_active_y,
      movement_keep_active_z: mcu_params.movement_keep_active_z,
      movement_home_at_boot_x: mcu_params.movement_home_at_boot_x,
      movement_home_at_boot_y: mcu_params.movement_home_at_boot_y,
      movement_home_at_boot_z: mcu_params.movement_home_at_boot_z,
      movement_invert_endpoints_x: mcu_params.movement_invert_endpoints_x,
      movement_invert_endpoints_y: mcu_params.movement_invert_endpoints_y,
      movement_invert_endpoints_z: mcu_params.movement_invert_endpoints_z,
      movement_enable_endpoints_x: mcu_params.movement_enable_endpoints_x,
      movement_enable_endpoints_y: mcu_params.movement_enable_endpoints_y,
      movement_enable_endpoints_z: mcu_params.movement_enable_endpoints_z,
      movement_invert_motor_x: mcu_params.movement_invert_motor_x,
      movement_invert_motor_y: mcu_params.movement_invert_motor_y,
      movement_invert_motor_z: mcu_params.movement_invert_motor_z,
      movement_secondary_motor_x: mcu_params.movement_secondary_motor_x,
      movement_secondary_motor_invert_x: mcu_params.movement_secondary_motor_invert_x,
      movement_steps_acc_dec_x: mcu_params.movement_steps_acc_dec_x,
      movement_steps_acc_dec_y: mcu_params.movement_steps_acc_dec_y,
      movement_steps_acc_dec_z: mcu_params.movement_steps_acc_dec_z,
      movement_stop_at_home_x: mcu_params.movement_stop_at_home_x,
      movement_stop_at_home_y: mcu_params.movement_stop_at_home_y,
      movement_stop_at_home_z: mcu_params.movement_stop_at_home_z,
      movement_home_up_x: mcu_params.movement_home_up_x,
      movement_home_up_y: mcu_params.movement_home_up_y,
      movement_home_up_z: mcu_params.movement_home_up_z,
      movement_step_per_mm_x: mcu_params.movement_step_per_mm_x,
      movement_step_per_mm_y: mcu_params.movement_step_per_mm_y,
      movement_step_per_mm_z: mcu_params.movement_step_per_mm_z,
      movement_min_spd_x: mcu_params.movement_min_spd_x,
      movement_min_spd_y: mcu_params.movement_min_spd_y,
      movement_min_spd_z: mcu_params.movement_min_spd_z,
      movement_home_spd_x: mcu_params.movement_home_spd_x,
      movement_home_spd_y: mcu_params.movement_home_spd_y,
      movement_home_spd_z: mcu_params.movement_home_spd_z,
      movement_max_spd_x: mcu_params.movement_max_spd_x,
      movement_max_spd_y: mcu_params.movement_max_spd_y,
      movement_max_spd_z: mcu_params.movement_max_spd_z,
      movement_invert_2_endpoints_x: mcu_params.movement_invert_2_endpoints_x,
      movement_invert_2_endpoints_y: mcu_params.movement_invert_2_endpoints_y,
      movement_invert_2_endpoints_z: mcu_params.movement_invert_2_endpoints_z,
      movement_motor_current_x: mcu_params.movement_motor_current_x,
      movement_motor_current_y: mcu_params.movement_motor_current_y,
      movement_motor_current_z: mcu_params.movement_motor_current_z,
      movement_stall_sensitivity_x: mcu_params.movement_stall_sensitivity_x,
      movement_stall_sensitivity_y: mcu_params.movement_stall_sensitivity_y,
      movement_stall_sensitivity_z: mcu_params.movement_stall_sensitivity_z,
      movement_microsteps_x: mcu_params.movement_microsteps_x,
      movement_microsteps_y: mcu_params.movement_microsteps_y,
      movement_microsteps_z: mcu_params.movement_microsteps_z,
      encoder_enabled_x: mcu_params.encoder_enabled_x,
      encoder_enabled_y: mcu_params.encoder_enabled_y,
      encoder_enabled_z: mcu_params.encoder_enabled_z,
      encoder_type_x: mcu_params.encoder_type_x,
      encoder_type_y: mcu_params.encoder_type_y,
      encoder_type_z: mcu_params.encoder_type_z,
      encoder_missed_steps_max_x: mcu_params.encoder_missed_steps_max_x,
      encoder_missed_steps_max_y: mcu_params.encoder_missed_steps_max_y,
      encoder_missed_steps_max_z: mcu_params.encoder_missed_steps_max_z,
      encoder_scaling_x: mcu_params.encoder_scaling_x,
      encoder_scaling_y: mcu_params.encoder_scaling_y,
      encoder_scaling_z: mcu_params.encoder_scaling_z,
      encoder_missed_steps_decay_x: mcu_params.encoder_missed_steps_decay_x,
      encoder_missed_steps_decay_y: mcu_params.encoder_missed_steps_decay_y,
      encoder_missed_steps_decay_z: mcu_params.encoder_missed_steps_decay_z,
      encoder_use_for_pos_x: mcu_params.encoder_use_for_pos_x,
      encoder_use_for_pos_y: mcu_params.encoder_use_for_pos_y,
      encoder_use_for_pos_z: mcu_params.encoder_use_for_pos_z,
      encoder_invert_x: mcu_params.encoder_invert_x,
      encoder_invert_y: mcu_params.encoder_invert_y,
      encoder_invert_z: mcu_params.encoder_invert_z,
      movement_axis_nr_steps_x: mcu_params.movement_axis_nr_steps_x,
      movement_axis_nr_steps_y: mcu_params.movement_axis_nr_steps_y,
      movement_axis_nr_steps_z: mcu_params.movement_axis_nr_steps_z,
      movement_stop_at_max_x: mcu_params.movement_stop_at_max_x,
      movement_stop_at_max_y: mcu_params.movement_stop_at_max_y,
      movement_stop_at_max_z: mcu_params.movement_stop_at_max_z,
      pin_guard_1_pin_nr: mcu_params.pin_guard_1_pin_nr,
      pin_guard_1_time_out: mcu_params.pin_guard_1_time_out,
      pin_guard_1_active_state: mcu_params.pin_guard_1_active_state,
      pin_guard_2_pin_nr: mcu_params.pin_guard_2_pin_nr,
      pin_guard_2_time_out: mcu_params.pin_guard_2_time_out,
      pin_guard_2_active_state: mcu_params.pin_guard_2_active_state,
      pin_guard_3_pin_nr: mcu_params.pin_guard_3_pin_nr,
      pin_guard_3_time_out: mcu_params.pin_guard_3_time_out,
      pin_guard_3_active_state: mcu_params.pin_guard_3_active_state,
      pin_guard_4_pin_nr: mcu_params.pin_guard_4_pin_nr,
      pin_guard_4_time_out: mcu_params.pin_guard_4_time_out,
      pin_guard_4_active_state: mcu_params.pin_guard_4_active_state,
      pin_guard_5_pin_nr: mcu_params.pin_guard_5_pin_nr,
      pin_guard_5_time_out: mcu_params.pin_guard_5_time_out,
      pin_guard_5_active_state: :pin_guard_5_active_state
    }
  end

  def changeset(mcu_params, params \\ %{}) do
    mcu_params
    |> cast(params, [
      :param_e_stop_on_mov_err,
      :param_mov_nr_retry,
      :movement_timeout_x,
      :movement_timeout_y,
      :movement_timeout_z,
      :movement_keep_active_x,
      :movement_keep_active_y,
      :movement_keep_active_z,
      :movement_home_at_boot_x,
      :movement_home_at_boot_y,
      :movement_home_at_boot_z,
      :movement_invert_endpoints_x,
      :movement_invert_endpoints_y,
      :movement_invert_endpoints_z,
      :movement_enable_endpoints_x,
      :movement_enable_endpoints_y,
      :movement_enable_endpoints_z,
      :movement_invert_motor_x,
      :movement_invert_motor_y,
      :movement_invert_motor_z,
      :movement_secondary_motor_x,
      :movement_secondary_motor_invert_x,
      :movement_steps_acc_dec_x,
      :movement_steps_acc_dec_y,
      :movement_steps_acc_dec_z,
      :movement_stop_at_home_x,
      :movement_stop_at_home_y,
      :movement_stop_at_home_z,
      :movement_home_up_x,
      :movement_home_up_y,
      :movement_home_up_z,
      :movement_step_per_mm_x,
      :movement_step_per_mm_y,
      :movement_step_per_mm_z,
      :movement_min_spd_x,
      :movement_min_spd_y,
      :movement_min_spd_z,
      :movement_home_spd_x,
      :movement_home_spd_y,
      :movement_home_spd_z,
      :movement_max_spd_x,
      :movement_max_spd_y,
      :movement_max_spd_z,
      :movement_invert_2_endpoints_x,
      :movement_invert_2_endpoints_y,
      :movement_invert_2_endpoints_z,
      :movement_motor_current_x,
      :movement_motor_current_y,
      :movement_motor_current_z,
      :movement_stall_sensitivity_x,
      :movement_stall_sensitivity_y,
      :movement_stall_sensitivity_z,
      :movement_microsteps_x,
      :movement_microsteps_y,
      :movement_microsteps_z,
      :encoder_enabled_x,
      :encoder_enabled_y,
      :encoder_enabled_z,
      :encoder_type_x,
      :encoder_type_y,
      :encoder_type_z,
      :encoder_missed_steps_max_x,
      :encoder_missed_steps_max_y,
      :encoder_missed_steps_max_z,
      :encoder_scaling_x,
      :encoder_scaling_y,
      :encoder_scaling_z,
      :encoder_missed_steps_decay_x,
      :encoder_missed_steps_decay_y,
      :encoder_missed_steps_decay_z,
      :encoder_use_for_pos_x,
      :encoder_use_for_pos_y,
      :encoder_use_for_pos_z,
      :encoder_invert_x,
      :encoder_invert_y,
      :encoder_invert_z,
      :movement_axis_nr_steps_x,
      :movement_axis_nr_steps_y,
      :movement_axis_nr_steps_z,
      :movement_stop_at_max_x,
      :movement_stop_at_max_y,
      :movement_stop_at_max_z,
      :pin_guard_1_pin_nr,
      :pin_guard_1_time_out,
      :pin_guard_1_active_state,
      :pin_guard_2_pin_nr,
      :pin_guard_2_time_out,
      :pin_guard_2_active_state,
      :pin_guard_3_pin_nr,
      :pin_guard_3_time_out,
      :pin_guard_3_active_state,
      :pin_guard_4_pin_nr,
      :pin_guard_4_time_out,
      :pin_guard_4_active_state,
      :pin_guard_5_pin_nr,
      :pin_guard_5_time_out,
      :pin_guard_5_active_state
    ])
  end
end


Refactor show method to use private method

defmodule EspiDni.ArticleController do
  use EspiDni.Web, :controller

  alias EspiDni.Article

  plug :authenticate
  plug :scrub_params, "article" when action in [:create, :update]

  def index(conn, _params) do
    team = conn.assigns.current_team
    render(conn, "index.html", articles: user_articles(conn), current_team: team)
  end

  def new(conn, _params) do
    changeset = Article.changeset(%Article{})
    render(conn, "new.html", changeset: changeset)
  end

  def create(conn, %{"article" => article_params}) do
    params = Map.merge(article_params, %{"user_id" => conn.assigns.current_user.id})
    changeset = Article.changeset(%Article{}, params)

    case Repo.insert(changeset) do
      {:ok, _article} ->
        conn
        |> put_flash(:info, "Article created successfully.")
        |> redirect(to: article_path(conn, :index))
      {:error, changeset} ->
        render(conn, "new.html", changeset: changeset)
    end
  end

  def show(conn, %{"id" => id}) do
    render(conn, "show.html", article: get_article(id))
  end

  def edit(conn, %{"id" => id}) do
    article = get_user_article(conn, id)
    changeset = Article.changeset(article)
    render(conn, "edit.html", article: article, changeset: changeset)
  end

  def update(conn, %{"id" => id, "article" => article_params}) do
    article = get_user_article(conn, id)
    changeset = Article.changeset(article, article_params)

    case Repo.update(changeset) do
      {:ok, article} ->
        conn
        |> put_flash(:info, "Article updated successfully.")
        |> redirect(to: article_path(conn, :show, article))
      {:error, changeset} ->
        render(conn, "edit.html", article: article, changeset: changeset)
    end
  end

  def delete(conn, %{"id" => id}) do
    article = get_user_article(conn, id)

    # Here we use delete! (with a bang) because we expect
    # it to always work (and if it does not, it will raise).
    Repo.delete!(article)

    conn
    |> put_flash(:info, "Article deleted successfully.")
    |> redirect(to: article_path(conn, :index))
  end

  defp user_articles(conn) do
    user_id = conn.assigns.current_user.id
    Repo.all(
      from article in Article,
      where: article.user_id == ^user_id
    )
  end

  defp get_user_article(conn, id) do
    user_id = conn.assigns.current_user.id
    Repo.one!(
      from article in Article,
      where: article.id == ^id,
      where: article.user_id == ^user_id
    )
  end

  defp authenticate(conn, _opts) do
    if conn.assigns.current_team && conn.assigns.current_user do
      conn
    else
      conn
      |> put_flash(:error, "You must be logged in to access that page")
      |> redirect(to: page_path(conn, :index))
      |> halt()
    end
  end

  defp get_article(id) do
    Article
    |> Article.with_view_counts
    |> Repo.get!(id)
  end
end

defmodule EspiDni.ArticleController do
  use EspiDni.Web, :controller

  alias EspiDni.Article

  plug :authenticate
  plug :scrub_params, "article" when action in [:create, :update]

  def index(conn, _params) do
    team = conn.assigns.current_team
    render(conn, "index.html", articles: user_articles(conn), current_team: team)
  end

  def new(conn, _params) do
    changeset = Article.changeset(%Article{})
    render(conn, "new.html", changeset: changeset)
  end

  def create(conn, %{"article" => article_params}) do
    params = Map.merge(article_params, %{"user_id" => conn.assigns.current_user.id})
    changeset = Article.changeset(%Article{}, params)

    case Repo.insert(changeset) do
      {:ok, _article} ->
        conn
        |> put_flash(:info, "Article created successfully.")
        |> redirect(to: article_path(conn, :index))
      {:error, changeset} ->
        render(conn, "new.html", changeset: changeset)
    end
  end

  def show(conn, %{"id" => id}) do
    article =
      Article
      |> Article.with_view_counts
      |> Repo.get!(id)

    render(conn, "show.html", article: article)
  end

  def edit(conn, %{"id" => id}) do
    article = get_user_article(conn, id)
    changeset = Article.changeset(article)
    render(conn, "edit.html", article: article, changeset: changeset)
  end

  def update(conn, %{"id" => id, "article" => article_params}) do
    article = get_user_article(conn, id)
    changeset = Article.changeset(article, article_params)

    case Repo.update(changeset) do
      {:ok, article} ->
        conn
        |> put_flash(:info, "Article updated successfully.")
        |> redirect(to: article_path(conn, :show, article))
      {:error, changeset} ->
        render(conn, "edit.html", article: article, changeset: changeset)
    end
  end

  def delete(conn, %{"id" => id}) do
    article = get_user_article(conn, id)

    # Here we use delete! (with a bang) because we expect
    # it to always work (and if it does not, it will raise).
    Repo.delete!(article)

    conn
    |> put_flash(:info, "Article deleted successfully.")
    |> redirect(to: article_path(conn, :index))
  end

  defp user_articles(conn) do
    user_id = conn.assigns.current_user.id
    Repo.all(
      from article in Article,
      where: article.user_id == ^user_id
    )
  end

  defp get_user_article(conn, id) do
    user_id = conn.assigns.current_user.id
    Repo.one!(
      from article in Article,
      where: article.id == ^id,
      where: article.user_id == ^user_id
    )
  end

  defp authenticate(conn, _opts) do
    if conn.assigns.current_team && conn.assigns.current_user do
      conn
    else
      conn
      |> put_flash(:error, "You must be logged in to access that page")
      |> redirect(to: page_path(conn, :index))
      |> halt()
    end
  end
end


Reformat Mix.Dep.Umbrella with mix format (#6790)

defmodule Mix.Dep.Umbrella do
  @moduledoc false

  @doc """
  Gets all umbrella dependencies in unloaded format.
  """
  def unloaded do
    config = Mix.Project.config()

    if apps_paths = Mix.Project.apps_paths(config) do
      env = Mix.env()
      from = Path.absname("mix.exs")
      build = Mix.Project.build_path(config)

      for {app, path} <- apps_paths do
        dest_path = Path.expand(path)
        build_path = Path.join([build, "lib", Atom.to_string(app)])
        opts = [path: path, dest: dest_path, from_umbrella: true, env: env, build: build_path]

        %Mix.Dep{
          scm: Mix.SCM.Path,
          app: app,
          requirement: nil,
          manager: :mix,
          status: {:ok, nil},
          from: from,
          opts: opts
        }
      end
    else
      []
    end
  end

  @doc """
  Gets all umbrella dependencies in the loaded format from cache (if available).
  """
  def cached do
    if project = Mix.Project.get() do
      key = {:umbrella_deps, Mix.env(), project}
      Mix.ProjectStack.read_cache(key) || Mix.ProjectStack.write_cache(key, loaded())
    else
      loaded()
    end
  end

  @doc """
  Gets all umbrella dependencies in the loaded format.
  """
  def loaded do
    deps = unloaded()
    apps = Enum.map(deps, & &1.app)

    Enum.map(deps, fn umbrella_dep ->
      umbrella_dep = Mix.Dep.Loader.load(umbrella_dep, nil)

      deps =
        Enum.filter(umbrella_dep.deps, fn dep ->
          Mix.Dep.available?(dep) and dep.app in apps
        end)

      %{umbrella_dep | deps: deps}
    end)
    |> Mix.Dep.Converger.topological_sort()
  end
end

defmodule Mix.Dep.Umbrella do
  @moduledoc false

  @doc """
  Gets all umbrella dependencies in unloaded format.
  """
  def unloaded do
    config = Mix.Project.config

    if apps_paths = Mix.Project.apps_paths(config) do
      env = Mix.env
      from = Path.absname("mix.exs")
      build = Mix.Project.build_path(config)

      for {app, path} <- apps_paths do
        opts = [path: path, dest: Path.expand(path), from_umbrella: true,
                env: env, build: Path.join([build, "lib", Atom.to_string(app)])]
        %Mix.Dep{scm: Mix.SCM.Path, app: app, requirement: nil,
                 manager: :mix, status: {:ok, nil}, from: from, opts: opts}
      end
    else
      []
    end
  end

  @doc """
  Gets all umbrella dependencies in the loaded format from cache (if available).
  """
  def cached do
    if project = Mix.Project.get do
      key = {:umbrella_deps, Mix.env, project}
      Mix.ProjectStack.read_cache(key) || Mix.ProjectStack.write_cache(key, loaded())
    else
      loaded()
    end
  end

  @doc """
  Gets all umbrella dependencies in the loaded format.
  """
  def loaded do
    deps = unloaded()
    apps = Enum.map(deps, &(&1.app))

    Enum.map(deps, fn umbrella_dep ->
      umbrella_dep = Mix.Dep.Loader.load(umbrella_dep, nil)
      deps = Enum.filter(umbrella_dep.deps, fn dep ->
        Mix.Dep.available?(dep) and dep.app in apps
      end)
      %{umbrella_dep | deps: deps}
    end) |> Mix.Dep.Converger.topological_sort
  end
end


Add apply, symbol? nil? true? and false?

defmodule Mal.Core do
  def namespace do
    %{
      "+" => fn [a, b] -> a + b end,
      "-" => fn [a, b] -> a - b end,
      "*" => fn [a, b] -> a * b end,
      "/" => fn [a, b] -> div(a, b) end,
      "=" => fn [a, b] -> a == b end,
      ">" => fn [a, b] -> a > b end,
      "<" => fn [a, b] -> a < b end,
      "<=" => fn [a, b] -> a <= b end,
      ">=" => fn [a, b] -> a >= b end,
      "concat" => &Enum.concat/1,
      "list?" => &list?/1,
      "empty?" => &empty?/1,
      "count" => &count/1,
      "pr-str" => &pr_str/1,
      "str" => &str/1,
      "prn" => &prn/1,
      "println" => &println/1,
      "slurp" => &slurp/1,
      "nth" => &nth/1,
      "first" => &first/1,
      "rest" => &rest/1,
      "map" => &map/1,
      "apply" => &apply/1,
      "symbol?" => &symbol?/1,
      "list" => fn args -> args end,
      "nil?" => fn [type] -> type == nil end,
      "true?" => fn [type] -> type == true end,
      "false?" => fn [type] -> type == false end,
      "read-string" => fn [input] -> Mal.Reader.read_str(input) end,
      "cons" => fn [prepend, list] -> [prepend | list] end,
      "throw" => fn [arg] -> throw({:error, arg}) end,
    }
  end

  def list?([arg]) when is_list(arg), do: true
  def list?([_arg]), do: false

  def empty?([[]]), do: true
  def empty?(_), do: false

  def count([arg]) when is_list(arg), do: length(arg)
  def count(_), do: 0

  def pr_str(args) do
    args
      |> Enum.map(&Mal.Printer.print_str/1)
      |> Enum.join(" ")
  end

  def str(args) do
    args
      |> Enum.map(&(Mal.Printer.print_str(&1, false)))
      |> Enum.join("")
  end

  def prn(args) do
    args
      |> pr_str
      |> IO.puts
    nil
  end

  def println(args) do
    args
      |> Enum.map(&(Mal.Printer.print_str(&1, false)))
      |> Enum.join(" ")
      |> IO.puts
    nil
  end

  def slurp([file_name]) do
    case File.read(file_name) do
      {:ok, content} -> content
      {:error, :enoent} -> throw({:error, "can't find file #{file_name}"})
      {:error, :eisdir} -> throw({:error, "can't read directory #{file_name}"})
      {:error, :eaccess} -> throw({:error, "missing permissions #{file_name}"})
      {:error, reason} -> throw({:error, "can't read file #{file_name}, #{reason}"})
    end
  end

  def nth([list, index]) do
    case Enum.at(list, index, :error) do
      :error -> throw({:error, "index out of bounds"})
      any -> any
    end
  end

  def first([[head | tail]]), do: head
  def first(_), do: nil

  def rest([[head | tail]]), do: tail
  def rest([[]]), do: []

  def map([{_function_type, function}, list]), do: do_map(function, list)
  def map([function, list]), do: do_map(function, list)

  defp do_map(function, list) do
    Enum.map(list, fn arg -> function.([arg]) end)
  end

  def apply([{_function_type, function} | tail]), do: do_apply(function, tail)
  def apply([function | tail]), do: do_apply(function, tail)

  def do_apply(function, tail) do
    [list | args] = tail
      |> Enum.reverse
    func_args = Enum.concat(list, args)
    function.(func_args)
  end

  def symbol?([{:symbol, _}]), do: true
  def symbol?(_), do: false
end

defmodule Mal.Core do
  def namespace do
    %{
      "+" => fn [a, b] -> a + b end,
      "-" => fn [a, b] -> a - b end,
      "*" => fn [a, b] -> a * b end,
      "/" => fn [a, b] -> div(a, b) end,
      "=" => fn [a, b] -> a == b end,
      ">" => fn [a, b] -> a > b end,
      "<" => fn [a, b] -> a < b end,
      "<=" => fn [a, b] -> a <= b end,
      ">=" => fn [a, b] -> a >= b end,
      "concat" => &Enum.concat/1,
      "list?" => &list?/1,
      "empty?" => &empty?/1,
      "count" => &count/1,
      "pr-str" => &pr_str/1,
      "str" => &str/1,
      "prn" => &prn/1,
      "println" => &println/1,
      "slurp" => &slurp/1,
      "nth" => &nth/1,
      "first" => &first/1,
      "rest" => &rest/1,
      "map" => &map/1,
      "list" => fn args -> args end,
      "read-string" => fn [input] -> Mal.Reader.read_str(input) end,
      "cons" => fn [prepend, list] -> [prepend | list] end,
      "throw" => fn [arg] -> throw({:error, arg}) end
    }
  end

  def list?([arg]) when is_list(arg), do: true
  def list?([_arg]), do: false

  def empty?([[]]), do: true
  def empty?(_), do: false

  def count([arg]) when is_list(arg), do: length(arg)
  def count(_), do: 0

  def pr_str(args) do
    args
      |> Enum.map(&Mal.Printer.print_str/1)
      |> Enum.join(" ")
  end

  def str(args) do
    args
      |> Enum.map(&(Mal.Printer.print_str(&1, false)))
      |> Enum.join("")
  end

  def prn(args) do
    args
      |> pr_str
      |> IO.puts
    nil
  end

  def println(args) do
    args
      |> Enum.map(&(Mal.Printer.print_str(&1, false)))
      |> Enum.join(" ")
      |> IO.puts
    nil
  end

  def slurp([file_name]) do
    case File.read(file_name) do
      {:ok, content} -> content
      {:error, :enoent} -> throw({:error, "can't find file #{file_name}"})
      {:error, :eisdir} -> throw({:error, "can't read directory #{file_name}"})
      {:error, :eaccess} -> throw({:error, "missing permissions #{file_name}"})
      {:error, reason} -> throw({:error, "can't read file #{file_name}, #{reason}"})
    end
  end

  def nth([list, index]) do
    case Enum.at(list, index, :error) do
      :error -> throw({:error, "index out of bounds"})
      any -> any
    end
  end

  def first([[head | tail]]), do: head
  def first(_), do: nil

  def rest([[head | tail]]), do: tail
  def rest([[]]), do: []

  def map([{:macro, function}, list]), do: do_map(function, list)
  def map([{:closure, function}, list]), do: do_map(function, list)
  def map([function, list]), do: do_map(function, list)

  defp do_map(function, list) do
    Enum.map(list, fn arg -> function.([arg]) end)
  end
end


Run the code formatter on Mix.Dep.Loader  (#6727)

# This module is responsible for loading dependencies
# of the current project. This module and its functions
# are private to Mix.
defmodule Mix.Dep.Loader do
  @moduledoc false

  import Mix.Dep, only: [ok?: 1, mix?: 1, rebar?: 1, make?: 1]

  @doc """
  Gets all direct children of the current `Mix.Project`
  as a `Mix.Dep` struct. Umbrella project dependencies
  are included as children.

  By default, it will filter all dependencies that does not match
  current environment, behaviour can be overridden via options.
  """
  def children() do
    mix_children([]) ++ Mix.Dep.Umbrella.unloaded()
  end

  @doc """
  Partitions loaded dependencies by environment.
  """
  def partition_by_env(deps, nil), do: {deps, []}
  def partition_by_env(deps, env), do: Enum.split_with(deps, &not skip?(&1, env))

  @doc """
  Checks if a dependency must be skipped according to the environment.
  """
  def skip?(_dep, nil), do: false
  def skip?(%Mix.Dep{status: {:divergedonly, _}}, _), do: false

  def skip?(%Mix.Dep{opts: opts}, env) do
    only = opts[:only]
    validate_only!(only)
    only != nil and env not in List.wrap(only)
  end

  @doc """
  Loads the given dependency information, including its
  latest status and children.
  """
  def load(%Mix.Dep{manager: manager, scm: scm, opts: opts} = dep, children) do
    manager = scm_manager(scm, opts) || manager || infer_manager(opts[:dest])

    dep = %{dep | manager: manager, status: scm_status(scm, opts)}

    {dep, children} =
      cond do
        not ok?(dep) ->
          {dep, []}

        mix?(dep) ->
          mix_dep(dep, children)

        # If not an explicit Rebar or Mix dependency
        # but came from Rebar, assume to be a Rebar dep.
        rebar?(dep) ->
          rebar_dep(dep, children, manager)

        make?(dep) ->
          make_dep(dep)

        true ->
          {dep, []}
      end

    %{validate_app(dep) | deps: attach_only(children, opts)}
  end

  @doc """
  Checks if a requirement from a dependency matches
  the given version.
  """
  def vsn_match(nil, _actual, _app), do: {:ok, true}

  def vsn_match(req, actual, app) do
    if Regex.regex?(req) do
      {:ok, actual =~ req}
    else
      case Version.parse(actual) do
        {:ok, version} ->
          case Version.parse_requirement(req) do
            {:ok, req} ->
              {:ok, Version.match?(version, req)}

            :error ->
              Mix.raise("Invalid requirement #{req} for app #{app}")
          end

        :error ->
          {:error, :nosemver}
      end
    end
  end

  ## Helpers

  def to_dep(tuple, from, manager \\ nil) do
    %{opts: opts} = dep = with_scm_and_app(tuple)
    %{dep | from: from, manager: opts[:manager] || manager}
  end

  defp with_scm_and_app({app, opts} = original) when is_atom(app) and is_list(opts) do
    with_scm_and_app(app, nil, opts, original)
  end

  defp with_scm_and_app({app, req} = original) when is_atom(app) do
    if is_binary(req) or Regex.regex?(req) do
      with_scm_and_app(app, req, [], original)
    else
      invalid_dep_format(original)
    end
  end

  defp with_scm_and_app({app, req, opts} = original) when is_atom(app) and is_list(opts) do
    if is_binary(req) or Regex.regex?(req) do
      with_scm_and_app(app, req, opts, original)
    else
      invalid_dep_format(original)
    end
  end

  defp with_scm_and_app(original) do
    invalid_dep_format(original)
  end

  defp with_scm_and_app(app, req, opts, original) do
    unless Keyword.keyword?(opts) do
      invalid_dep_format(original)
    end

    bin_app = Atom.to_string(app)

    dest = Path.join(Mix.Project.deps_path(), bin_app)
    build = Path.join([Mix.Project.build_path(), "lib", bin_app])

    opts =
      opts
      |> Keyword.put(:dest, dest)
      |> Keyword.put(:build, build)

    {scm, opts} = get_scm(app, opts)

    {scm, opts} =
      if !scm && Mix.Hex.ensure_installed?(app) do
        _ = Mix.Hex.start()
        get_scm(app, opts)
      else
        {scm, opts}
      end

    unless scm do
      Mix.raise(
        "Could not find an SCM for dependency #{inspect(app)} from #{inspect(Mix.Project.get())}"
      )
    end

    %Mix.Dep{
      scm: scm,
      app: app,
      requirement: req,
      status: scm_status(scm, opts),
      opts: Keyword.put_new(opts, :env, :prod)
    }
  end

  defp get_scm(app, opts) do
    Enum.find_value(Mix.SCM.available(), {nil, opts}, fn scm ->
      (new = scm.accepts_options(app, opts)) && {scm, new}
    end)
  end

  # Notice we ignore Make dependencies because the
  # file based heuristic will always figure it out.
  @scm_managers ~w(mix rebar rebar3)a

  defp scm_manager(scm, opts) do
    managers = scm.managers(opts)
    Enum.find(@scm_managers, &(&1 in managers))
  end

  defp scm_status(scm, opts) do
    if scm.checked_out?(opts) do
      {:ok, nil}
    else
      {:unavailable, opts[:dest]}
    end
  end

  defp infer_manager(dest) do
    cond do
      any_of?(dest, ["mix.exs"]) ->
        :mix

      any_of?(dest, ["rebar", "rebar.config", "rebar.config.script", "rebar.lock"]) ->
        :rebar3

      any_of?(dest, ["Makefile", "Makefile.win"]) ->
        :make

      true ->
        nil
    end
  end

  defp any_of?(dest, files) do
    Enum.any?(files, &File.regular?(Path.join(dest, &1)))
  end

  defp invalid_dep_format(dep) do
    Mix.raise("""
    Dependency specified in the wrong format:

        #{inspect(dep)}

    Expected:

        {app, opts} | {app, requirement} | {app, requirement, opts}

    Where:

        app :: atom
        requirement :: String.t | Regex.t
        opts :: keyword

    If you want to skip the requirement (not recommended), use ">= 0.0.0".
    """)
  end

  ## Fetching

  # We need to override the dependencies so they mirror
  # the :only requirement in the parent.
  defp attach_only(deps, opts) do
    if only = opts[:only] do
      Enum.map(deps, fn %{opts: opts} = dep ->
        %{dep | opts: Keyword.put_new(opts, :only, only)}
      end)
    else
      deps
    end
  end

  defp mix_dep(%Mix.Dep{opts: opts} = dep, nil) do
    Mix.Dep.in_dependency(dep, fn _ ->
      opts =
        if Mix.Project.umbrella?() do
          Keyword.put_new(opts, :app, false)
        else
          opts
        end

      child_opts =
        if opts[:from_umbrella] do
          []
        else
          [env: Keyword.fetch!(opts, :env)]
        end

      deps = mix_children(child_opts) ++ Mix.Dep.Umbrella.unloaded()
      {%{dep | opts: opts}, deps}
    end)
  end

  # If we have a Mix dependency that came from a remote converger,
  # we just use the dependencies given by the remote converger,
  # we don't need to load the mix.exs at all. We can only do this
  # because umbrella projects are not supported in remotes.
  defp mix_dep(%Mix.Dep{opts: opts} = dep, children) do
    from = Path.join(opts[:dest], "mix.exs")
    deps = Enum.map(children, &to_dep(&1, from))
    {dep, deps}
  end

  defp rebar_dep(%Mix.Dep{app: app, opts: opts, extra: overrides} = dep, children, manager) do
    config = File.cd!(opts[:dest], fn -> Mix.Rebar.load_config(".") end)

    config = Mix.Rebar.apply_overrides(app, config, overrides)

    deps =
      if children do
        from = Path.join(opts[:dest], "rebar.config")
        # Pass the manager because deps of a Rebar project need
        # to default to Rebar if we cannot chose a manager from
        # files in the dependency
        Enum.map(children, &to_dep(&1, from, manager))
      else
        rebar_children(config, manager, opts[:dest])
      end

    {%{dep | extra: config}, deps}
  end

  defp make_dep(dep) do
    {dep, []}
  end

  defp validate_only!(only) do
    for entry <- List.wrap(only), not is_atom(entry) do
      Mix.raise(
        "Expected :only in dependency to be an atom or a list of atoms, got: #{inspect(only)}"
      )
    end

    only
  end

  defp mix_children(opts) do
    from = Path.absname("mix.exs")

    (Mix.Project.config()[:deps] || [])
    |> Enum.map(&to_dep(&1, from))
    |> partition_by_env(opts[:env])
    |> elem(0)
  end

  defp rebar_children(root_config, manager, dest) do
    from = Path.absname(Path.join(dest, "rebar.config"))

    Mix.Rebar.recur(root_config, fn config ->
      overrides = overrides(manager, config)

      config
      |> Mix.Rebar.deps()
      |> Enum.map(fn dep -> %{to_dep(dep, from, manager) | extra: overrides} end)
    end)
    |> Enum.concat()
  end

  defp overrides(:rebar3, config), do: config[:overrides] || []
  defp overrides(_, _config), do: []

  defp validate_app(%Mix.Dep{opts: opts, requirement: req, app: app} = dep) do
    opts_app = opts[:app]

    cond do
      not ok?(dep) ->
        dep

      recently_fetched?(dep) ->
        %{dep | status: :compile}

      opts_app == false ->
        dep

      true ->
        path = if is_binary(opts_app), do: opts_app, else: "ebin/#{app}.app"
        path = Path.expand(path, opts[:build])
        %{dep | status: app_status(path, app, req)}
    end
  end

  defp recently_fetched?(%Mix.Dep{opts: opts, scm: scm}) do
    scm.fetchable? &&
      Mix.Utils.stale?([Path.join(opts[:dest], ".fetch")], [
        Path.join(opts[:build], ".compile.fetch")
      ])
  end

  defp app_status(app_path, app, req) do
    case :file.consult(app_path) do
      {:ok, [{:application, ^app, config}]} ->
        case List.keyfind(config, :vsn, 0) do
          {:vsn, actual} when is_list(actual) ->
            actual = IO.iodata_to_binary(actual)

            case vsn_match(req, actual, app) do
              {:ok, true} -> {:ok, actual}
              {:ok, false} -> {:nomatchvsn, actual}
              {:error, error} -> {error, actual}
            end

          {:vsn, actual} ->
            {:invalidvsn, actual}

          nil ->
            {:invalidvsn, nil}
        end

      {:ok, _} ->
        {:invalidapp, app_path}

      {:error, _} ->
        {:noappfile, app_path}
    end
  end
end

# This module is responsible for loading dependencies
# of the current project. This module and its functions
# are private to Mix.
defmodule Mix.Dep.Loader do
  @moduledoc false

  import Mix.Dep, only: [ok?: 1, mix?: 1, rebar?: 1, make?: 1]

  @doc """
  Gets all direct children of the current `Mix.Project`
  as a `Mix.Dep` struct. Umbrella project dependencies
  are included as children.

  By default, it will filter all dependencies that does not match
  current environment, behaviour can be overridden via options.
  """
  def children() do
    mix_children([]) ++ Mix.Dep.Umbrella.unloaded
  end

  @doc """
  Partitions loaded dependencies by environment.
  """
  def partition_by_env(deps, nil), do: {deps, []}
  def partition_by_env(deps, env), do: Enum.split_with(deps, &not skip?(&1, env))

  @doc """
  Checks if a dependency must be skipped according to the environment.
  """
  def skip?(_dep, nil), do: false
  def skip?(%Mix.Dep{status: {:divergedonly, _}}, _), do: false
  def skip?(%Mix.Dep{opts: opts}, env) do
    only = opts[:only]
    validate_only!(only)
    only != nil and env not in List.wrap(only)
  end

  @doc """
  Loads the given dependency information, including its
  latest status and children.
  """
  def load(%Mix.Dep{manager: manager, scm: scm, opts: opts} = dep, children) do
    manager = scm_manager(scm, opts) ||
              manager ||
              infer_manager(opts[:dest])

    dep = %{dep | manager: manager, status: scm_status(scm, opts)}

    {dep, children} =
      cond do
        not ok?(dep) ->
          {dep, []}

        mix?(dep) ->
          mix_dep(dep, children)

        # If not an explicit Rebar or Mix dependency
        # but came from Rebar, assume to be a Rebar dep.
        rebar?(dep) ->
          rebar_dep(dep, children, manager)

        make?(dep) ->
          make_dep(dep)

        true ->
          {dep, []}
      end

    %{validate_app(dep) | deps: attach_only(children, opts)}
  end

  @doc """
  Checks if a requirement from a dependency matches
  the given version.
  """
  def vsn_match(nil, _actual, _app),
    do: {:ok, true}
  def vsn_match(req, actual, app) do
    if Regex.regex?(req) do
      {:ok, actual =~ req}
    else
      case Version.parse(actual) do
        {:ok, version} ->
          case Version.parse_requirement(req) do
            {:ok, req} ->
              {:ok, Version.match?(version, req)}
            :error ->
              Mix.raise "Invalid requirement #{req} for app #{app}"
          end
        :error ->
          {:error, :nosemver}
      end
    end
  end

  ## Helpers

  def to_dep(tuple, from, manager \\ nil) do
    %{opts: opts} = dep = with_scm_and_app(tuple)
    %{dep | from: from, manager: opts[:manager] || manager}
  end

  defp with_scm_and_app({app, opts} = original) when is_atom(app) and is_list(opts) do
    with_scm_and_app(app, nil, opts, original)
  end

  defp with_scm_and_app({app, req} = original) when is_atom(app) do
    if is_binary(req) or Regex.regex?(req) do
      with_scm_and_app(app, req, [], original)
    else
      invalid_dep_format(original)
    end
  end

  defp with_scm_and_app({app, req, opts} = original) when is_atom(app) and is_list(opts)  do
    if is_binary(req) or Regex.regex?(req) do
      with_scm_and_app(app, req, opts, original)
    else
      invalid_dep_format(original)
    end
  end

  defp with_scm_and_app(original) do
    invalid_dep_format(original)
  end

  defp with_scm_and_app(app, req, opts, original) do
    unless Keyword.keyword?(opts) do
      invalid_dep_format(original)
    end

    bin_app = Atom.to_string(app)

    dest  = Path.join(Mix.Project.deps_path, bin_app)
    build = Path.join([Mix.Project.build_path, "lib", bin_app])
    opts  = opts
            |> Keyword.put(:dest, dest)
            |> Keyword.put(:build, build)

    {scm, opts} = get_scm(app, opts)

    {scm, opts} =
      if !scm && Mix.Hex.ensure_installed?(app) do
        _ = Mix.Hex.start()
        get_scm(app, opts)
      else
        {scm, opts}
      end

    unless scm do
      Mix.raise "Could not find an SCM for dependency #{inspect app} from #{inspect Mix.Project.get}"
    end

    %Mix.Dep{
      scm: scm,
      app: app,
      requirement: req,
      status: scm_status(scm, opts),
      opts: Keyword.put_new(opts, :env, :prod)}
  end

  defp get_scm(app, opts) do
    Enum.find_value Mix.SCM.available, {nil, opts}, fn scm ->
      (new = scm.accepts_options(app, opts)) && {scm, new}
    end
  end

  # Notice we ignore Make dependencies because the
  # file based heuristic will always figure it out.
  @scm_managers ~w(mix rebar rebar3)a

  defp scm_manager(scm, opts) do
    managers = scm.managers(opts)
    Enum.find(@scm_managers, &(&1 in managers))
  end

  defp scm_status(scm, opts) do
    if scm.checked_out?(opts) do
      {:ok, nil}
    else
      {:unavailable, opts[:dest]}
    end
  end

  defp infer_manager(dest) do
    cond do
      any_of?(dest, ["mix.exs"]) ->
        :mix
      any_of?(dest, ["rebar", "rebar.config", "rebar.config.script", "rebar.lock"]) ->
        :rebar3
      any_of?(dest, ["Makefile", "Makefile.win"]) ->
        :make
      true ->
        nil
    end
  end

  defp any_of?(dest, files) do
    Enum.any?(files, &File.regular?(Path.join(dest, &1)))
  end

  defp invalid_dep_format(dep) do
    Mix.raise """
    Dependency specified in the wrong format:

        #{inspect dep}

    Expected:

        {app, opts} | {app, requirement} | {app, requirement, opts}

    Where:

        app :: atom
        requirement :: String.t | Regex.t
        opts :: keyword

    If you want to skip the requirement (not recommended), use ">= 0.0.0".
    """
  end

  ## Fetching

  # We need to override the dependencies so they mirror
  # the :only requirement in the parent.
  defp attach_only(deps, opts) do
    if only = opts[:only] do
      Enum.map(deps, fn %{opts: opts} = dep ->
        %{dep | opts: Keyword.put_new(opts, :only, only)}
      end)
    else
      deps
    end
  end

  defp mix_dep(%Mix.Dep{opts: opts} = dep, nil) do
    Mix.Dep.in_dependency(dep, fn _ ->
      opts =
        if Mix.Project.umbrella? do
          Keyword.put_new(opts, :app, false)
        else
          opts
        end

      child_opts =
        if opts[:from_umbrella] do
          []
        else
          [env: Keyword.fetch!(opts, :env)]
        end

      deps = mix_children(child_opts) ++ Mix.Dep.Umbrella.unloaded
      {%{dep | opts: opts}, deps}
    end)
  end

  # If we have a Mix dependency that came from a remote converger,
  # we just use the dependencies given by the remote converger,
  # we don't need to load the mix.exs at all. We can only do this
  # because umbrella projects are not supported in remotes.
  defp mix_dep(%Mix.Dep{opts: opts} = dep, children) do
    from = Path.join(opts[:dest], "mix.exs")
    deps = Enum.map(children, &to_dep(&1, from))
    {dep, deps}
  end

  defp rebar_dep(%Mix.Dep{app: app, opts: opts, extra: overrides} = dep, children, manager) do
    config =
      File.cd!(opts[:dest], fn -> Mix.Rebar.load_config(".") end)

    config =
      Mix.Rebar.apply_overrides(app, config, overrides)

    deps =
      if children do
        from = Path.join(opts[:dest], "rebar.config")
        # Pass the manager because deps of a Rebar project need
        # to default to Rebar if we cannot chose a manager from
        # files in the dependency
        Enum.map(children, &to_dep(&1, from, manager))
      else
        rebar_children(config, manager, opts[:dest])
      end

    {%{dep | extra: config}, deps}
  end

  defp make_dep(dep) do
    {dep, []}
  end

  defp validate_only!(only) do
    for entry <- List.wrap(only), not is_atom(entry) do
      Mix.raise "Expected :only in dependency to be an atom or a list of atoms, got: #{inspect only}"
    end
    only
  end

  defp mix_children(opts) do
    from = Path.absname("mix.exs")
    (Mix.Project.config[:deps] || [])
    |> Enum.map(&to_dep(&1, from))
    |> partition_by_env(opts[:env])
    |> elem(0)
  end

  defp rebar_children(root_config, manager, dest) do
    from = Path.absname(Path.join(dest, "rebar.config"))
    Mix.Rebar.recur(root_config, fn config ->
      overrides = overrides(manager, config)
      config
      |> Mix.Rebar.deps()
      |> Enum.map(fn dep -> %{to_dep(dep, from, manager) | extra: overrides} end)
    end) |> Enum.concat
  end

  defp overrides(:rebar3, config), do: config[:overrides] || []
  defp overrides(_, _config), do: []

  defp validate_app(%Mix.Dep{opts: opts, requirement: req, app: app} = dep) do
    opts_app = opts[:app]

    cond do
      not ok?(dep) ->
        dep
      recently_fetched?(dep) ->
        %{dep | status: :compile}
      opts_app == false ->
        dep
      true ->
        path = if is_binary(opts_app), do: opts_app, else: "ebin/#{app}.app"
        path = Path.expand(path, opts[:build])
        %{dep | status: app_status(path, app, req)}
    end
  end

  defp recently_fetched?(%Mix.Dep{opts: opts, scm: scm}) do
    scm.fetchable? &&
      Mix.Utils.stale?([Path.join(opts[:dest], ".fetch")],
                       [Path.join(opts[:build], ".compile.fetch")])
  end

  defp app_status(app_path, app, req) do
    case :file.consult(app_path) do
      {:ok, [{:application, ^app, config}]} ->
        case List.keyfind(config, :vsn, 0) do
          {:vsn, actual} when is_list(actual) ->
            actual = IO.iodata_to_binary(actual)
            case vsn_match(req, actual, app) do
              {:ok, true} -> {:ok, actual}
              {:ok, false} -> {:nomatchvsn, actual}
              {:error, error} -> {error, actual}
            end
          {:vsn, actual} ->
            {:invalidvsn, actual}
          nil ->
            {:invalidvsn, nil}
        end
      {:ok, _} -> {:invalidapp, app_path}
      {:error, _} -> {:noappfile, app_path}
    end
  end
end