decodes array fields

decodes array fields

defmodule Geolix.Database do
  use Bitwise, only_operators: true

  @metadata_marker <<171, 205, 239>> <> "MaxMind.com"

  @ctrl_types [ :extended,  :pointer,    :utf8_string, :double,
                :bytes,     :uint16,     :uint32,      :map,
                :int32,     :uint64,     :uint128,     :array,
                :container, :end_marker, :boolean,     :float ]

  def read(db_dir) do
    cities    = read_cities(db_dir)
    countries = read_countries(db_dir)

    cond do
      is_list(cities) and is_list(countries) -> cities ++ countries
      is_tuple(cities)    -> cities
      is_tuple(countries) -> countries
      true -> { :error, "Unknown error" }
    end
  end

  defp read_cities(_) do
    []
  end

  defp read_countries(db_dir) do
    db_file    = db_dir <> "GeoLite2-Country.mmdb"
    db_file_gz = db_file <> ".gz"

    cond do
      File.regular?(db_file)    -> parse_countries({ :regular, db_file })
      File.regular?(db_file_gz) -> parse_countries({ :gzip , db_file_gz})
      true -> { :error, "Failed to find 'GeoLite2-Country.mmdb[.gz]' in given path '#{db_dir}'!" }
    end
  end

  defp parse_countries({ :regular, db_file }) do
    stream_countries(File.binstream!(db_file, [:read], 1))
  end
  defp parse_countries({ :gzip, db_file }) do
    stream_countries(File.binstream!(db_file, [:read, :compressed], 1))
  end

  defp stream_countries(stream) do
    meta_stream = drop_until_meta(stream)
    meta_data   = decode(meta_stream)

    IO.inspect(meta_data)
    []
  end

  defp drop_until_meta(stream) do
    stream = Enum.drop_while(stream, fn(c) -> c != String.at(@metadata_marker, 0) end)
    marker = Enum.take(stream, byte_size(@metadata_marker)) |> Enum.join()

    if marker == @metadata_marker do
      Enum.drop(stream, byte_size(@metadata_marker))
    else
      drop_until_meta(Enum.drop(stream, 1))
    end
  end

  defp decode(stream) do
    case Enum.take(stream, 1) do
      ctrl_byte when is_list(ctrl_byte) and 1 == length(ctrl_byte) ->
        ctrl_code = hd(ctrl_byte) |> byte_to_code()
        ctrl_type = Enum.at(@ctrl_types, ctrl_code >>> 5)

        if :extended == ctrl_type do
          stream    = Enum.drop(stream, 1)
          ext_code  = Enum.take(stream, 1) |> hd() |> byte_to_code()
          ctrl_type = Enum.at(@ctrl_types, ext_code + 7)
        end

        { stream, read_size } = get_meta_size(Enum.drop(stream, 1), ctrl_code)

        decode_type(stream, ctrl_type, read_size)
      _ ->
        IO.puts("Invalid byte read from stream?!")
        { stream, nil }
    end
  end

  defp byte_to_code(byte) do
    :io_lib.format("~w", bitstring_to_list(byte))
        |> hd()
        |> list_to_integer()
  end

  defp get_meta_size(stream, code) do
    # bitwise and with 0x1f
    case code &&& 31 do
      _size when 29 == _size ->
        { stream, size } = decode_uint(stream, 1)
        { stream, 29 + size }
      _size when 30 == _size ->
        { stream, size } = decode_uint(stream, 2)
        { stream, 285 + size }
      _ -> { stream, code &&& 31 }
    end
  end

  defp decode_type(stream, type, size) do
    case type do
      :array       -> decode_array(stream, size)
      :double      -> decode_double(stream, size)
      :map         -> decode_map(stream, size)
      :utf8_string -> decode_utf8_string(stream, size)
      :uint16      -> decode_uint(stream, size)
      :uint32      -> decode_uint(stream, size)
      :uint64      -> decode_uint(stream, size)
      _ ->
        IO.puts "unhandled type #{type}: " <> inspect(Enum.take(stream, size))
        { Enum.drop(stream, size), type }
    end
  end

  defp decode_array(stream, size) do
    decode_array(stream, [], size)
  end

  defp decode_array(stream, arr, size) when 0 < size do
    { stream, elem } = decode(stream)

    decode_array(stream, arr ++ [elem], size - 1)
  end
  defp decode_array(stream, arr, 0) do
    { stream, arr }
  end

  defp decode_double(stream, size) do
    { Enum.drop(stream, size), :double }
  end

  defp decode_map(stream, size) do
    decode_map(stream, [], size)
  end

  defp decode_map(stream, map, size) when 0 < size do
    { stream, key } = decode(stream)
    { stream, val } = decode(stream)

    decode_map(stream, map ++ [{ key, val }], size - 1)
  end
  defp decode_map(stream, map, 0) do
    { stream, map }
  end

  defp decode_uint(stream, size) when 0 < size do
    bytes  = Enum.take(stream, size) |> Enum.join()
    stream = Enum.drop(stream, size)

    uint   =  Enum.map(bitstring_to_list(bytes), fn(x) -> integer_to_binary(x, 16) end)
              |> Enum.join()
              |> String.to_char_list!()
              |> list_to_integer(16)

    { stream, uint }
  end
  defp decode_uint(stream, 0) do
    { stream, 0 }
  end

  defp decode_utf8_string(stream, size) do
    string = Enum.take(stream, size) |> Enum.join()
    stream = Enum.drop(stream, size)

    { stream, string }
  end
end

defmodule Geolix.Database do
  use Bitwise, only_operators: true

  @metadata_marker <<171, 205, 239>> <> "MaxMind.com"

  @ctrl_types [ :extended,  :pointer,    :utf8_string, :double,
                :bytes,     :uint16,     :uint32,      :map,
                :int32,     :uint64,     :uint128,     :array,
                :container, :end_marker, :boolean,     :float ]

  def read(db_dir) do
    cities    = read_cities(db_dir)
    countries = read_countries(db_dir)

    cond do
      is_list(cities) and is_list(countries) -> cities ++ countries
      is_tuple(cities)    -> cities
      is_tuple(countries) -> countries
      true -> { :error, "Unknown error" }
    end
  end

  defp read_cities(_) do
    []
  end

  defp read_countries(db_dir) do
    db_file    = db_dir <> "GeoLite2-Country.mmdb"
    db_file_gz = db_file <> ".gz"

    cond do
      File.regular?(db_file)    -> parse_countries({ :regular, db_file })
      File.regular?(db_file_gz) -> parse_countries({ :gzip , db_file_gz})
      true -> { :error, "Failed to find 'GeoLite2-Country.mmdb[.gz]' in given path '#{db_dir}'!" }
    end
  end

  defp parse_countries({ :regular, db_file }) do
    stream_countries(File.binstream!(db_file, [:read], 1))
  end
  defp parse_countries({ :gzip, db_file }) do
    stream_countries(File.binstream!(db_file, [:read, :compressed], 1))
  end

  defp stream_countries(stream) do
    meta_stream = drop_until_meta(stream)
    meta_data   = decode(meta_stream)

    IO.inspect(meta_data)
    []
  end

  defp drop_until_meta(stream) do
    stream = Enum.drop_while(stream, fn(c) -> c != String.at(@metadata_marker, 0) end)
    marker = Enum.take(stream, byte_size(@metadata_marker)) |> Enum.join()

    if marker == @metadata_marker do
      Enum.drop(stream, byte_size(@metadata_marker))
    else
      drop_until_meta(Enum.drop(stream, 1))
    end
  end

  defp decode(stream) do
    case Enum.take(stream, 1) do
      ctrl_byte when is_list(ctrl_byte) and 1 == length(ctrl_byte) ->
        ctrl_code = hd(ctrl_byte) |> byte_to_code()
        ctrl_type = Enum.at(@ctrl_types, ctrl_code >>> 5)

        if :extended == ctrl_type do
          ext_code  = Enum.take(Enum.drop(stream, 1), 1) |> hd() |> byte_to_code()
          ctrl_type = Enum.at(@ctrl_types, ext_code + 7)
        end

        { stream, read_size } = get_meta_size(Enum.drop(stream, 1), ctrl_code)

        decode_type(stream, ctrl_type, read_size)
      _ -> nil
    end
  end

  defp byte_to_code(byte) do
    :io_lib.format("~w", bitstring_to_list(byte))
        |> hd()
        |> list_to_integer()
  end

  defp get_meta_size(stream, code) do
    # bitwise and with 0x1f
    case code &&& 31 do
      _size when 29 == _size ->
        { stream, size } = decode_uint32(stream, 1)
        { stream, 29 + size }
      _size when 30 == _size ->
        { stream, size } = decode_uint32(stream, 2)
        { stream, 285 + size }
      _ -> { stream, code &&& 31 }
    end
  end

  defp decode_type(stream, type, size) do
    case type do
      :double      -> decode_double(stream, size)
      :map         -> decode_map(stream, size)
      :utf8_string -> decode_utf8_string(stream, size)
      :uint16      -> decode_uint16(stream, size)
      :uint32      -> decode_uint32(stream, size)
      _            -> { Enum.drop(stream, size), type }
    end
  end

  defp decode_double(stream, size) do
    { Enum.drop(stream, size), :double }
  end

  defp decode_map(stream, size) do
    decode_map(stream, [], size)
  end

  defp decode_map(stream, map, size) when 0 < size do
    { stream, key } = decode(stream)
    { stream, val } = decode(stream)

    decode_map(stream, map ++ [{ key, val }], size - 1)
  end
  defp decode_map(stream, map, 0) do
    { stream, map }
  end

  defp decode_uint16(stream, size) do
    decode_uint32(stream, size)
  end

  defp decode_uint32(stream, size) when 0 < size do
    bytes  = Enum.take(stream, size) |> Enum.join()
    stream = Enum.drop(stream, size)

    uint   =  Enum.map(bitstring_to_list(bytes), fn(x) -> integer_to_binary(x, 16) end)
              |> Enum.join()
              |> String.to_char_list!()
              |> list_to_integer(16)

    { stream, uint }
  end
  defp decode_uint32(stream, 0) do
    { stream, 0 }
  end

  defp decode_utf8_string(stream, size) do
    string = Enum.take(stream, size) |> Enum.join()
    stream = Enum.drop(stream, size)

    { stream, string }
  end
end


Alias warning -> warn in send_message

Alias warning -> warn in send_message

defmodule Farmbot.CeleryScript.AST.Node.SendMessage do
  @moduledoc false
  use Farmbot.CeleryScript.AST.Node
  use Farmbot.Logger
  allow_args [:message, :message_type]

  # credo:disable-for-this-file

  def execute(%{message: m, message_type: type}, channels, env) do
    env = mutate_env(env)
    {:ok, env, channels} = do_reduce(channels, env, [])
    bindings = fetch_bindings(env)
    case sanatize(m) do
      {:ok, sanatized} ->
        msg = EEx.eval_string(sanatized, bindings)
        case type do
          "debug" ->
            Logger.debug 2, msg, channels: channels
            {:ok, env}
          "info" ->
            Logger.info 2, msg, channels: channels
            {:ok, env}
          "busy" ->
            Logger.busy 2, msg, channels: channels
            {:ok, env}
          "success" ->
            Logger.success 2, msg, channels: channels
            {:ok, env}
          "warn" ->
            Logger.warn 2, msg, channels: channels
            {:ok, env}
          "warning" ->
            Logger.warn 2, msg, channels: channels
            {:ok, env}
          "error" ->
            Logger.error 2, msg, channels: channels
            {:ok, env}
          other ->
            {:error, "unknown type: #{other}", env}
        end
      {:error, reason} -> {:error, reason, env}
    end

  rescue
    e in CompileError ->
      case Exception.message(e) do
        "nofile:1: undefined function " <> undef ->
          Logger.error 2, "Unknown variable: #{undef}"
          {:error, :unknown_variable, env}
        _ ->
          {:error, Exception.message(e), env}
      end
    e -> reraise(e, System.stacktrace())
  end

  defp sanatize(message, global_acc \\ "", local_acc \\ "", mode \\ :global)

  defp sanatize(<<>>, global, _local, _mode), do: {:ok, global}

  defp sanatize(<<"{{", rest :: binary >>, acc, _local, _mode) do
    sanatize(rest, acc <> "<%=", "", :local)
  end

  defp sanatize(<<"}}", rest ::binary >>, global_acc, local_acc, _) do
    case sanatize_local(local_acc) do
      {:ok, sanatized} ->
        sanatize(rest, global_acc <> sanatized <> "%>", "", :global)
      {:error, reason} -> {:error, reason}
    end
  end

  defp sanatize(<<char, rest :: binary>>, global, _local, :global) do
    sanatize(rest, global <> <<char>>, "", :global)
  end

  defp sanatize(<<char, rest :: binary>>, global, local, :local) do
    sanatize(rest, global, local <> <<char>>, :local)
  end

  defp sanatize_local(local) do
    cond do
      String.contains?(local, "(") or String.contains?(local, ")") ->
        {:error, "templates may not contain special characters: `(` or `)`"}
      String.contains?(local, ".") ->
        {:error, "templates may not contain special character: `.`"}
      String.contains?(local, ":") ->
        {:error, "templates may not contain special character: `.`"}
      String.contains?(local, "[") or String.contains?(local, "]") ->
        {:error, "templates may not contain special characters: `[` or `]`"}
      String.contains?(local, "\"") or String.contains?(local, "\'") or String.contains?(local, "\`") ->
        {:error, "templates may not sub strings."}
      true -> {:ok, local}
    end
  end

  defp fetch_bindings(env) do
    bot_state = Farmbot.BotState.force_state_push()
    pins = Enum.map(bot_state.pins, fn({pin, %{value: value}}) -> {:"pin#{pin}", value} end)
    location = Enum.map(bot_state.location_data.position, fn({axis, val}) -> {axis, val} end)
    env.vars ++ pins ++ location
  end

  defp do_reduce([%{args: %{channel_name: channel}} | rest], env, acc) do
    do_reduce(rest, env, [channel | acc])
  end

  defp do_reduce([], env, acc), do: {:ok, env, acc}
end

defmodule Farmbot.CeleryScript.AST.Node.SendMessage do
  @moduledoc false
  use Farmbot.CeleryScript.AST.Node
  use Farmbot.Logger
  allow_args [:message, :message_type]

  # credo:disable-for-this-file

  def execute(%{message: m, message_type: type}, channels, env) do
    env = mutate_env(env)
    {:ok, env, channels} = do_reduce(channels, env, [])
    bindings = fetch_bindings(env)
    case sanatize(m) do
      {:ok, sanatized} ->
        msg = EEx.eval_string(sanatized, bindings)
        case type do
          "debug" ->
            Logger.debug 2, msg, channels: channels
            {:ok, env}
          "info" ->
            Logger.info 2, msg, channels: channels
            {:ok, env}
          "busy" ->
            Logger.busy 2, msg, channels: channels
            {:ok, env}
          "success" ->
            Logger.success 2, msg, channels: channels
            {:ok, env}
          "warn" ->
            Logger.warn 2, msg, channels: channels
            {:ok, env}
          "error" ->
            Logger.error 2, msg, channels: channels
            {:ok, env}
          other ->
            {:error, "unknown type: #{other}", env}
        end
      {:error, reason} -> {:error, reason, env}
    end

  rescue
    e in CompileError ->
      case Exception.message(e) do
        "nofile:1: undefined function " <> undef ->
          Logger.error 2, "Unknown variable: #{undef}"
          {:error, :unknown_variable, env}
        _ ->
          {:error, Exception.message(e), env}
      end
    e -> reraise(e, System.stacktrace())
  end

  defp sanatize(message, global_acc \\ "", local_acc \\ "", mode \\ :global)

  defp sanatize(<<>>, global, _local, _mode), do: {:ok, global}

  defp sanatize(<<"{{", rest :: binary >>, acc, _local, _mode) do
    sanatize(rest, acc <> "<%=", "", :local)
  end

  defp sanatize(<<"}}", rest ::binary >>, global_acc, local_acc, _) do
    case sanatize_local(local_acc) do
      {:ok, sanatized} ->
        sanatize(rest, global_acc <> sanatized <> "%>", "", :global)
      {:error, reason} -> {:error, reason}
    end
  end

  defp sanatize(<<char, rest :: binary>>, global, _local, :global) do
    sanatize(rest, global <> <<char>>, "", :global)
  end

  defp sanatize(<<char, rest :: binary>>, global, local, :local) do
    sanatize(rest, global, local <> <<char>>, :local)
  end

  defp sanatize_local(local) do
    cond do
      String.contains?(local, "(") or String.contains?(local, ")") ->
        {:error, "templates may not contain special characters: `(` or `)`"}
      String.contains?(local, ".") ->
        {:error, "templates may not contain special character: `.`"}
      String.contains?(local, ":") ->
        {:error, "templates may not contain special character: `.`"}
      String.contains?(local, "[") or String.contains?(local, "]") ->
        {:error, "templates may not contain special characters: `[` or `]`"}
      String.contains?(local, "\"") or String.contains?(local, "\'") or String.contains?(local, "\`") ->
        {:error, "templates may not sub strings."}
      true -> {:ok, local}
    end
  end

  defp fetch_bindings(env) do
    bot_state = Farmbot.BotState.force_state_push()
    pins = Enum.map(bot_state.pins, fn({pin, %{value: value}}) -> {:"pin#{pin}", value} end)
    location = Enum.map(bot_state.location_data.position, fn({axis, val}) -> {axis, val} end)
    env.vars ++ pins ++ location
  end

  defp do_reduce([%{args: %{channel_name: channel}} | rest], env, acc) do
    do_reduce(rest, env, [channel | acc])
  end

  defp do_reduce([], env, acc), do: {:ok, env, acc}
end


database: fix Dogma warnings

database: fix Dogma warnings

defmodule BorsNG.Database.Migrate do
  @moduledoc """
  Custom Ecto database migration task to be used in compiled releases.

  Since Mix tasks are not available after compiling, implement our own version
  of `mix ecto.create` and `mix ecto.migrate`.

  `BorsNG.Database.Migrate.run_standalone` should be called from external
  scripts to perform the required work and exit afterwards.
  `BorsNG.Database.Migrate.up` should be called to run the migrations but
  continue running normally afterwards.
  """

  def repos, do: Application.get_env(:bors_database, :ecto_repos, [])

  def run_standalone do
    up(:permanent)

    :init.stop()
  end

  def up(type \\ :temporary) do
    {:ok, _} = Application.ensure_all_started(:bors_database, type)

    Enum.each repos(), fn(repo) ->
      case create_storage_for(repo) do
        :seed ->
          run_migrations_for(repo)
          run_seeds_for(repo)
        :migrate ->
          run_migrations_for(repo)
      end
    end
  end

  def create_storage_for(repo) do
    case repo.__adapter__.storage_up(repo.config) do
      :ok -> :seed
      {:error, :already_up} -> :migrate
      {:error, term} when is_binary(term) ->
        raise RuntimeError, "The database for #{inspect repo} couldn't be " <>
                            "created: #{term}"
      {:error, term} ->
        raise RuntimeError, "The database for #{inspect repo} couldn't be " <>
                            "created: #{inspect term}"
    end
  end

  def run_migrations_for(repo) do
    app = Keyword.get(repo.config, :otp_app)
    IO.puts "Running migrations for #{app}"

    Ecto.Migrator.run(repo, migrations_path(repo), :up, all: true)
  end

  def run_seeds_for(repo) do
    seed_script = seeds_path(repo)

    if File.exists?(seed_script) do
      app = Keyword.get(repo.config, :otp_app)
      IO.puts "Running seed script for #{app}"

      Code.eval_file(seed_script)
    end
  end

  def migrations_path(repo), do: priv_path_for(repo, "migrations")

  def seeds_path(repo), do: priv_path_for(repo, "seeds.exs")

  def priv_dir(app), do: :code.priv_dir(app)

  def priv_path_for(repo, filename) do
    app = Keyword.get(repo.config, :otp_app)
    repo_underscore = repo |> Module.split |> List.last |> Macro.underscore
    Path.join([priv_dir(app), repo_underscore, filename])
  end
end

defmodule BorsNG.Database.Migrate do
  def repos, do: Application.get_env(:bors_database, :ecto_repos, [])

  def run_standalone do
    up()

    :init.stop()
  end

  def up do
    {:ok, _} = Application.ensure_all_started(:bors_database, :permanent)

    Enum.each repos(), fn(repo) ->
      case create_storage_for(repo) do
        :seed ->
          run_migrations_for(repo)
          run_seeds_for(repo)
        :migrate ->
          run_migrations_for(repo)
      end
    end
  end

  def create_storage_for(repo) do
    case repo.__adapter__.storage_up(repo.config) do
      :ok -> :seed
      {:error, :already_up} -> :migrate
      {:error, term} when is_binary(term) ->
        raise RuntimeError, "The database for #{inspect repo} couldn't be created: #{term}"
      {:error, term} ->
        raise RuntimeError, "The database for #{inspect repo} couldn't be created: #{inspect term}"
    end
  end

  def run_migrations_for(repo) do
    app = Keyword.get(repo.config, :otp_app)
    IO.puts "Running migrations for #{app}"

    Ecto.Migrator.run(repo, migrations_path(repo), :up, all: true)
  end

  def run_seeds_for(repo) do
    seed_script = seeds_path(repo)

    if File.exists?(seed_script) do
      app = Keyword.get(repo.config, :otp_app)
      IO.puts "Running seed script for #{app}"

      Code.eval_file(seed_script)
    end
  end

  def migrations_path(repo), do: priv_path_for(repo, "migrations")

  def seeds_path(repo), do: priv_path_for(repo, "seeds.exs")

  def priv_dir(app), do: "#{:code.priv_dir(app)}"

  def priv_path_for(repo, filename) do
    app = Keyword.get(repo.config, :otp_app)
    repo_underscore = repo |> Module.split |> List.last |> Macro.underscore
    Path.join([priv_dir(app), repo_underscore, filename])
  end
end


Run the code formatter on Mix.CLI (#6843)

defmodule Mix.CLI do
  @moduledoc false

  @doc """
  Runs Mix according to the command line arguments.
  """
  def main(args \\ System.argv()) do
    Mix.Local.append_archives()
    Mix.Local.append_paths()

    if env_variable_activated?("MIX_QUIET"), do: Mix.shell(Mix.Shell.Quiet)
    if env_variable_activated?("MIX_DEBUG"), do: Mix.debug(true)

    case check_for_shortcuts(args) do
      :help ->
        Mix.shell().info("Mix is a build tool for Elixir")
        display_usage()

      :version ->
        display_version()

      nil ->
        proceed(args)
    end
  end

  defp proceed(args) do
    load_dot_config()
    load_mix_exs()
    {task, args} = get_task(args)
    ensure_hex(task)
    change_env(task)
    run_task(task, args)
  end

  defp load_mix_exs() do
    file = System.get_env("MIX_EXS") || "mix.exs"

    _ =
      if File.regular?(file) do
        Code.load_file(file)
      end
  end

  defp get_task(["-" <> _ | _]) do
    task = "mix #{Mix.Project.config()[:default_task]}"

    Mix.shell().error(
      "** (Mix) Mix only recognizes the flags --help and --version.\n" <>
        "You may have wanted to invoke a task instead, such as #{inspect(task)}"
    )

    display_usage()
    exit({:shutdown, 1})
  end

  defp get_task([h | t]) do
    {h, t}
  end

  defp get_task([]) do
    case Mix.Project.get() do
      nil ->
        Mix.shell().error(
          "** (Mix) \"mix\" with no arguments must be executed in a directory with a mix.exs file"
        )

        display_usage()
        exit({:shutdown, 1})

      _ ->
        {Mix.Project.config()[:default_task], []}
    end
  end

  defp run_task(name, args) do
    try do
      ensure_no_slashes(name)
      Mix.Task.run("loadconfig")
      Mix.Task.run(name, args)
    rescue
      # We only rescue exceptions in the Mix namespace, all
      # others pass through and will explode on the users face
      exception ->
        stacktrace = System.stacktrace()

        if Map.get(exception, :mix) && not Mix.debug?() do
          mod = exception.__struct__ |> Module.split() |> Enum.at(0, "Mix")
          Mix.shell().error("** (#{mod}) #{Exception.message(exception)}")
          exit({:shutdown, 1})
        else
          reraise exception, stacktrace
        end
    end
  end

  defp env_variable_activated?(name) do
    System.get_env(name) in ~w(1 true)
  end

  defp ensure_hex("local.hex"), do: :ok
  defp ensure_hex(_task), do: Mix.Hex.ensure_updated?()

  defp ensure_no_slashes(task) do
    if String.contains?(task, "/") do
      raise Mix.NoTaskError, task: task
    end
  end

  defp change_env(task) do
    if env = preferred_cli_env(task) do
      Mix.env(env)

      if project = Mix.Project.pop() do
        %{name: name, file: file} = project
        Mix.Project.push(name, file)
      end
    end
  end

  defp preferred_cli_env(task) do
    if System.get_env("MIX_ENV") do
      nil
    else
      task = String.to_atom(task)
      Mix.Project.config()[:preferred_cli_env][task] || Mix.Task.preferred_cli_env(task)
    end
  end

  defp load_dot_config do
    path = Path.join(Mix.Utils.mix_home(), "config.exs")

    if File.regular?(path) do
      Mix.Task.run("loadconfig", [path])
    end
  end

  defp display_version do
    IO.puts(:erlang.system_info(:system_version))
    IO.puts("Mix " <> System.build_info()[:build])
  end

  defp display_usage do
    Mix.shell().info("""

    Usage: mix [task]

    Examples:

        mix             - Invokes the default task (mix run) in a project
        mix new PATH    - Creates a new Elixir project at the given path
        mix help        - Lists all available tasks
        mix help TASK   - Prints documentation for a given task

    The --help and --version flags can be given instead of a task for usage and versioning information.
    """)
  end

  # Check for --help or --version in the args
  defp check_for_shortcuts([arg]) when arg in ["--help", "-h"], do: :help

  defp check_for_shortcuts([arg]) when arg in ["--version", "-v"], do: :version

  defp check_for_shortcuts(_), do: nil
end

defmodule Mix.CLI do
  @moduledoc false

  @doc """
  Runs Mix according to the command line arguments.
  """
  def main(args \\ System.argv) do
    Mix.Local.append_archives
    Mix.Local.append_paths

    if env_variable_activated?("MIX_QUIET"), do: Mix.shell(Mix.Shell.Quiet)
    if env_variable_activated?("MIX_DEBUG"), do: Mix.debug(true)

    case check_for_shortcuts(args) do
      :help ->
        Mix.shell.info "Mix is a build tool for Elixir"
        display_usage()
      :version ->
        display_version()
      nil ->
        proceed(args)
    end
  end

  defp proceed(args) do
    load_dot_config()
    load_mix_exs()
    {task, args} = get_task(args)
    ensure_hex(task)
    change_env(task)
    run_task(task, args)
  end

  defp load_mix_exs() do
    file = System.get_env("MIX_EXS") || "mix.exs"
    _ = if File.regular?(file) do
      Code.load_file(file)
    end
  end

  defp get_task(["-" <> _ | _]) do
    task = "mix #{Mix.Project.config[:default_task]}"
    Mix.shell.error "** (Mix) Mix only recognizes the flags --help and --version.\n" <>
                    "You may have wanted to invoke a task instead, such as #{inspect(task)}"
    display_usage()
    exit({:shutdown, 1})
  end

  defp get_task([h | t]) do
    {h, t}
  end

  defp get_task([]) do
    case Mix.Project.get do
      nil ->
        Mix.shell.error "** (Mix) \"mix\" with no arguments must be executed in a directory with a mix.exs file"
        display_usage()
        exit({:shutdown, 1})
      _ ->
        {Mix.Project.config[:default_task], []}
    end
  end

  defp run_task(name, args) do
    try do
      ensure_no_slashes(name)
      Mix.Task.run "loadconfig"
      Mix.Task.run name, args
    rescue
      # We only rescue exceptions in the Mix namespace, all
      # others pass through and will explode on the users face
      exception ->
        stacktrace = System.stacktrace

        if Map.get(exception, :mix) && not Mix.debug? do
          mod = exception.__struct__ |> Module.split() |> Enum.at(0, "Mix")
          Mix.shell.error "** (#{mod}) #{Exception.message(exception)}"
          exit({:shutdown, 1})
        else
          reraise exception, stacktrace
        end
    end
  end

  defp env_variable_activated?(name) do
    System.get_env(name) in ~w(1 true)
  end

  defp ensure_hex("local.hex"),
    do: :ok
  defp ensure_hex(_task),
    do: Mix.Hex.ensure_updated?()

  defp ensure_no_slashes(task) do
    if String.contains?(task, "/") do
      raise Mix.NoTaskError, task: task
    end
  end

  defp change_env(task) do
    if env = preferred_cli_env(task) do
      Mix.env(env)
      if project = Mix.Project.pop do
        %{name: name, file: file} = project
        Mix.Project.push name, file
      end
    end
  end

  defp preferred_cli_env(task) do
    if System.get_env("MIX_ENV") do
      nil
    else
      task = String.to_atom(task)
      Mix.Project.config[:preferred_cli_env][task] || Mix.Task.preferred_cli_env(task)
    end
  end

  defp load_dot_config do
    path = Path.join(Mix.Utils.mix_home, "config.exs")
    if File.regular?(path) do
      Mix.Task.run "loadconfig", [path]
    end
  end

  defp display_version do
    IO.puts :erlang.system_info(:system_version)
    IO.puts "Mix " <> System.build_info[:build]
  end

  defp display_usage do
    Mix.shell.info """

    Usage: mix [task]

    Examples:

        mix             - Invokes the default task (mix run) in a project
        mix new PATH    - Creates a new Elixir project at the given path
        mix help        - Lists all available tasks
        mix help TASK   - Prints documentation for a given task

    The --help and --version flags can be given instead of a task for usage and versioning information.
    """
  end

  # Check for --help or --version in the args
  defp check_for_shortcuts([arg]) when arg in ["--help", "-h"],
    do: :help

  defp check_for_shortcuts([arg]) when arg in ["--version", "-v"],
    do: :version

  defp check_for_shortcuts(_),
    do: nil
end


Websocket handler added to the config

Websocket handler added to the config

defmodule Mix.Tasks.Weber do

    @moduledoc """

       Create a new weber project template.

       Usage:

         mix weber /home/user/myWebApp - Creates myWebApp directory with weber project skeleton.
         mix weber --version - Prints weber version.
    """

    @shortdoc "Create a new weber project"

    use Mix.Task

    import Path
    import File
    import Mix.Generator

    @version Weber.Mixfile.project[:version]

    def run([]) do
        usage
    end

    def run(["--help"]) do
        usage
    end

    def run(["--version"]) do
        Mix.shell.info "Weber v#{@version}"
    end

    def run([args]) do
        # new project's root directory
        directoryName = args
        # create project directory
        case mkdir(directoryName) do
            :ok -> :ok
            err -> :io.format("[Weber error] Can't create project directory. Error: ~p~n", [err])
        end

        #
        # create project skeleton
        #
        path = absname directoryName
        basePath = basename directoryName

        create_directory path <> <<"/lib">>
        create_directory path <> <<"/lib/static">>
        create_directory path <> <<"/lib/views">>
        create_directory path <> <<"/lib/models">>
        create_directory path <> <<"/lib/controllers">>
        create_directory path <> <<"/lib/helpers">>
        create_directory path <> <<"/test">>

        create_file path <> <<"/start.sh">>, (start directoryName)
        create_file path <> <<"/README.md">>, (readme basePath)
        create_file path <> <<"/.gitignore">>, gitignore
        create_file path <> <<"/mix.exs">>, (project basePath)
        create_file path <> <<"/lib/app.ex">>, (app basePath)
        create_file path <> <<"/lib/route.ex">>, (route basePath)
        create_file path <> <<"/lib/config.ex">>, config
        create_file path <> <<"/lib/controllers/main.ex">>, main_controller(basePath)
        create_file path <> <<"/lib/views/main.html">>, main_template(basePath)
        create_file path <> <<"/test/test_helper.exs">>, test
        create_file path <> <<"/test/">> <> (String.capitalize basePath) <> <<"test.exs">>, test_app(basePath)

        chmod(path <> "/start.sh", 0755)

    end

    def route(app) do
        proj = String.capitalize app
        """
        defmodule Route do

            import Weber.Route

            @route on("/", :#{proj}.Main, :action)

            def get_route do
                @route
            end
        end
        """
    end

    def readme(basePath) do
        """
        #{basePath}
        =====

        """
    end

    def gitignore do
        """
        /ebin
        /deps
        erl_crash.dump
        """
    end

    def project(projectName) do
        proj = String.capitalize projectName

        """
        defmodule #{proj}.Mixfile do
            use Mix.Project

            def project do
                [
                    app: :#{projectName},
                    version: "0.0.1",
                    deps: deps
                ]
            end

            def application do
                [
                    applications: [:weber],
                    mod: {#{proj}, []}
                ]
            end

            defp deps do
                [
                    { :weber, github: "0xAX/weber", compile: "mix deps.get && mix compile" }
                ]
            end
        end
        """
    end

    def app(projectName) do
        proj = String.capitalize projectName
        """
        defmodule #{proj} do

            import Weber

            def start(_type, _args) do
                {:ok, root} = :file.get_cwd()
                run_weber(:#{proj}, Route.get_route, root, Config.config)
            end

            def stop(_state) do
               :ok
            end
        end
        """
    end

    def config do
        """
        defmodule Config do

            def config do
                [webserver:
                    [http_host: "localhost",
                     http_port: 8080,
                     acceptors: 100,
                     ssl: false,
                     cacertfile_path: "",
                     certfile_path: "",
                     keyfile_path: "",

                     #
                     # websocket settings
                     #
                     ws: true
                     ws_mod: :Handler
                    ]
                ]
            end

        end
        """
    end

    def usage do
        """
        Usage:

          mix weber /home/user/testWebApp -- creates new weber web application
          mix weber --version -- shows weber version
          mix weber --help    -- show weber help
          mix weber --run     -- runs current weber web application
        """
    end

    def main_controller(app) do
        proj = String.capitalize(app) <> ".Main"
        """
        defmodule #{proj} do

            def action("GET", []) do
                {:render, [project: "#{app}"]}
            end

        end
        """
    end

    def main_template(app) do
        proj = String.capitalize(app)
        """
        <!DOCTYPE HTML>

                <title>#{proj}</title>

                Hello, <%= project %>

        """
    end

    def start(directoryName) do
        """
        #!/usr/bin/env sh

        if [ ! -f deps ]; then
            mix deps.get && mix compile
        fi

        export ERL_LIBS="$ERL_LIBS:#{directoryName}"
        exec iex -S mix
        """
    end

    def test() do
        """
        ExUnit.start
        """
    end

    def test_app(app) do
        path = (String.capitalize app) <> "Test"
        """
        defmodule #{path} do
            use ExUnit.Case

            test "the truth" do
                assert(true)
            end
        end
        """
    end

end

defmodule Mix.Tasks.Weber do

    @moduledoc """

       Create a new weber project template.

       Usage:

         mix weber /home/user/myWebApp - Creates myWebApp directory with weber project skeleton.
         mix weber --version - Prints weber version.
    """

    @shortdoc "Create a new weber project"

    use Mix.Task

    import Path
    import File
    import Mix.Generator

    @version Weber.Mixfile.project[:version]

    def run([]) do
        usage
    end

    def run(["--help"]) do
        usage
    end

    def run(["--version"]) do
        Mix.shell.info "Weber v#{@version}"
    end

    def run([args]) do
        # new project's root directory
        directoryName = args
        # create project directory
        case mkdir(directoryName) do
            :ok -> :ok
            err -> :io.format("[Weber error] Can't create project directory. Error: ~p~n", [err])
        end

        #
        # create project skeleton
        #
        path = absname directoryName
        basePath = basename directoryName

        create_directory path <> <<"/lib">>
        create_directory path <> <<"/lib/static">>
        create_directory path <> <<"/lib/views">>
        create_directory path <> <<"/lib/models">>
        create_directory path <> <<"/lib/controllers">>
        create_directory path <> <<"/lib/helpers">>
        create_directory path <> <<"/test">>

        create_file path <> <<"/start.sh">>, (start directoryName)
        create_file path <> <<"/README.md">>, (readme basePath)
        create_file path <> <<"/.gitignore">>, gitignore
        create_file path <> <<"/mix.exs">>, (project basePath)
        create_file path <> <<"/lib/app.ex">>, (app basePath)
        create_file path <> <<"/lib/route.ex">>, (route basePath)
        create_file path <> <<"/lib/config.ex">>, config
        create_file path <> <<"/lib/controllers/main.ex">>, main_controller(basePath)
        create_file path <> <<"/lib/views/main.html">>, main_template(basePath)
        create_file path <> <<"/test/test_helper.exs">>, test
        create_file path <> <<"/test/">> <> (String.capitalize basePath) <> <<"test.exs">>, test_app(basePath)

        chmod(path <> "/start.sh", 0755)

    end

    def route(app) do
        proj = String.capitalize app
        """
        defmodule Route do

            import Weber.Route

            @route on("/", :#{proj}.Main, :action)

            def get_route do
                @route
            end
        end
        """
    end

    def readme(basePath) do
        """
        #{basePath}
        =====

        """
    end

    def gitignore do
        """
        /ebin
        /deps
        erl_crash.dump
        """
    end

    def project(projectName) do
        proj = String.capitalize projectName

        """
        defmodule #{proj}.Mixfile do
            use Mix.Project

            def project do
                [
                    app: :#{projectName},
                    version: "0.0.1",
                    deps: deps
                ]
            end

            def application do
                [
                    applications: [:weber],
                    mod: {#{proj}, []}
                ]
            end

            defp deps do
                [
                    { :weber, github: "0xAX/weber", compile: "mix deps.get && mix compile" }
                ]
            end
        end
        """
    end

    def app(projectName) do
        proj = String.capitalize projectName
        """
        defmodule #{proj} do

            import Weber

            def start(_type, _args) do
                {:ok, root} = :file.get_cwd()
                run_weber(:#{proj}, Route.get_route, root, Config.config)
            end

            def stop(_state) do
               :ok
            end
        end
        """
    end

    def config do
        """
        defmodule Config do

            def config do
                [webserver:
                    [http_host: "localhost",
                     http_port: 8080,
                     acceptors: 100,
                     ssl: false,
                     cacertfile_path: "",
                     certfile_path: "",
                     keyfile_path: "",

                     #
                     # websocket settings
                     #
                     ws: true
                    ]
                ]
            end

        end
        """
    end

    def usage do
        """
        Usage:

          mix weber /home/user/testWebApp -- creates new weber web application
          mix weber --version -- shows weber version
          mix weber --help    -- show weber help
          mix weber --run     -- runs current weber web application
        """
    end

    def main_controller(app) do
        proj = String.capitalize(app) <> ".Main"
        """
        defmodule #{proj} do

            def action("GET", []) do
                {:render, [project: "#{app}"]}
            end

        end
        """
    end

    def main_template(app) do
        proj = String.capitalize(app)
        """
        <!DOCTYPE HTML>

                <title>#{proj}</title>

                Hello, <%= project %>

        """
    end

    def start(directoryName) do
        """
        #!/usr/bin/env sh

        if [ ! -f deps ]; then
            mix deps.get && mix compile
        fi

        export ERL_LIBS="$ERL_LIBS:#{directoryName}"
        exec iex -S mix
        """
    end

    def test() do
        """
        ExUnit.start
        """
    end

    def test_app(app) do
        path = (String.capitalize app) <> "Test"
        """
        defmodule #{path} do
            use ExUnit.Case

            test "the truth" do
                assert(true)
            end
        end
        """
    end

end


Generate Rooms API (partially, excluding extension-related ones)

# Code generated by `$ mix hipchat.generate`
defmodule Hipchat.V2.Rooms do
  @moduledoc """
  HipChat V2 Rooms API module.
  """

  alias Hipchat.{Client, Httpc}

  @endpoint "https://api.hipchat.com/v2"

  @doc """
  [https://www.hipchat.com/docs/apiv2/method/add_member](https://www.hipchat.com/docs/apiv2/method/add_member)
  """
  @spec add_member(Client.t, String.t, String.t, map) :: Httpc.res_t
  def add_member(client, room_id_or_name, user_id_or_email, body) do
    Httpc.request(:put,
                  "#{@endpoint}/room/#{room_id_or_name}/member/#{user_id_or_email}",
                  {:form, Map.to_list(body)},
                  Client.headers(client),
                  Client.options(client, []))
  end

  @doc """
  [https://www.hipchat.com/docs/apiv2/method/create_room](https://www.hipchat.com/docs/apiv2/method/create_room)
  """
  @spec create_room(Client.t, map) :: Httpc.res_t
  def create_room(client, body) do
    Httpc.request(:post,
                  "#{@endpoint}/room",
                  {:form, Map.to_list(body)},
                  Client.headers(client),
                  Client.options(client, []))
  end

  @doc """
  [https://www.hipchat.com/docs/apiv2/method/create_room_action](https://www.hipchat.com/docs/apiv2/method/create_room_action)
  """
  @spec create_room_action(Client.t, String.t, String.t, map) :: Httpc.res_t
  def create_room_action(client, room_id_or_name, key, body) do
    Httpc.request(:put,
                  "#{@endpoint}/room/#{room_id_or_name}/extension/action/#{key}",
                  {:form, Map.to_list(body)},
                  Client.headers(client),
                  Client.options(client, []))
  end

  @doc """
  [https://www.hipchat.com/docs/apiv2/method/delete_room](https://www.hipchat.com/docs/apiv2/method/delete_room)
  """
  @spec delete_room(Client.t, String.t) :: Httpc.res_t
  def delete_room(client, room_id_or_name) do
    Httpc.request(:delete,
                  "#{@endpoint}/room/#{room_id_or_name}",
                  "",
                  Client.headers(client),
                  Client.options(client, []))
  end

  @doc """
  [https://www.hipchat.com/docs/apiv2/method/delete_room_action](https://www.hipchat.com/docs/apiv2/method/delete_room_action)
  """
  @spec delete_room_action(Client.t, String.t, String.t) :: Httpc.res_t
  def delete_room_action(client, room_id_or_name, key) do
    Httpc.request(:delete,
                  "#{@endpoint}/room/#{room_id_or_name}/extension/action/#{key}",
                  "",
                  Client.headers(client),
                  Client.options(client, []))
  end

  @doc """
  [https://www.hipchat.com/docs/apiv2/method/delete_room_avatar](https://www.hipchat.com/docs/apiv2/method/delete_room_avatar)
  """
  @spec delete_room_avatar(Client.t, String.t) :: Httpc.res_t
  def delete_room_avatar(client, room_id_or_name) do
    Httpc.request(:delete,
                  "#{@endpoint}/room/#{room_id_or_name}/avatar",
                  "",
                  Client.headers(client),
                  Client.options(client, []))
  end

  @doc """
  [https://www.hipchat.com/docs/apiv2/method/get_all_members](https://www.hipchat.com/docs/apiv2/method/get_all_members)
  """
  @spec get_all_members(Client.t, String.t, Client.query_params_t) :: Httpc.res_t
  def get_all_members(client, room_id_or_name, query_params) do
    Httpc.request(:get,
                  "#{@endpoint}/room/#{room_id_or_name}/member",
                  "",
                  Client.headers(client),
                  Client.options(client, query_params))
  end

  @doc """
  [https://www.hipchat.com/docs/apiv2/method/get_all_participants](https://www.hipchat.com/docs/apiv2/method/get_all_participants)
  """
  @spec get_all_participants(Client.t, String.t, Client.query_params_t) :: Httpc.res_t
  def get_all_participants(client, room_id_or_name, query_params) do
    Httpc.request(:get,
                  "#{@endpoint}/room/#{room_id_or_name}/participant",
                  "",
                  Client.headers(client),
                  Client.options(client, query_params))
  end

  @doc """
  [https://www.hipchat.com/docs/apiv2/method/get_all_rooms](https://www.hipchat.com/docs/apiv2/method/get_all_rooms)
  """
  @spec get_all_rooms(Client.t, Client.query_params_t) :: Httpc.res_t
  def get_all_rooms(client, query_params) do
    Httpc.request(:get,
                  "#{@endpoint}/room",
                  "",
                  Client.headers(client),
                  Client.options(client, query_params))
  end

  @doc """
  [https://www.hipchat.com/docs/apiv2/method/view_recent_room_history](https://www.hipchat.com/docs/apiv2/method/view_recent_room_history)
  """
  @spec get_recent_room_history(Client.t, String.t, Client.query_params_t) :: Httpc.res_t
  def get_recent_room_history(client, room_id_or_name, query_params) do
    Httpc.request(:get,
                  "#{@endpoint}/room/#{room_id_or_name}/history/latest",
                  "",
                  Client.headers(client),
                  Client.options(client, query_params))
  end

  @doc """
  [https://www.hipchat.com/docs/apiv2/method/get_room](https://www.hipchat.com/docs/apiv2/method/get_room)
  """
  @spec get_room(Client.t, String.t) :: Httpc.res_t
  def get_room(client, room_id_or_name) do
    Httpc.request(:get,
                  "#{@endpoint}/room/#{room_id_or_name}",
                  "",
                  Client.headers(client),
                  Client.options(client, []))
  end

  @doc """
  [https://www.hipchat.com/docs/apiv2/method/get_room_action](https://www.hipchat.com/docs/apiv2/method/get_room_action)
  """
  @spec get_room_action(Client.t, String.t, String.t) :: Httpc.res_t
  def get_room_action(client, room_id_or_name, key) do
    Httpc.request(:get,
                  "#{@endpoint}/room/#{room_id_or_name}/extension/action/#{key}",
                  "",
                  Client.headers(client),
                  Client.options(client, []))
  end

  @doc """
  [https://www.hipchat.com/docs/apiv2/method/get_room_avatar](https://www.hipchat.com/docs/apiv2/method/get_room_avatar)
  """
  @spec get_room_avatar(Client.t, String.t) :: Httpc.res_t
  def get_room_avatar(client, room_id_or_name) do
    Httpc.request(:get,
                  "#{@endpoint}/room/#{room_id_or_name}/avatar",
                  "",
                  Client.headers(client),
                  Client.options(client, []))
  end

  @doc """
  [https://www.hipchat.com/docs/apiv2/method/view_room_history](https://www.hipchat.com/docs/apiv2/method/view_room_history)
  """
  @spec get_room_history(Client.t, String.t, Client.query_params_t) :: Httpc.res_t
  def get_room_history(client, room_id_or_name, query_params) do
    Httpc.request(:get,
                  "#{@endpoint}/room/#{room_id_or_name}/history",
                  "",
                  Client.headers(client),
                  Client.options(client, query_params))
  end

  @doc """
  [https://www.hipchat.com/docs/apiv2/method/get_room_message](https://www.hipchat.com/docs/apiv2/method/get_room_message)
  """
  @spec get_room_message(Client.t, String.t, String.t, Client.query_params_t) :: Httpc.res_t
  def get_room_message(client, room_id_or_name, message_id, query_params) do
    Httpc.request(:get,
                  "#{@endpoint}/room/#{room_id_or_name}/history/#{message_id}",
                  "",
                  Client.headers(client),
                  Client.options(client, query_params))
  end

  @doc """
  [https://www.hipchat.com/docs/apiv2/method/get_room_statistics](https://www.hipchat.com/docs/apiv2/method/get_room_statistics)
  """
  @spec get_room_statistics(Client.t, String.t) :: Httpc.res_t
  def get_room_statistics(client, room_id_or_name) do
    Httpc.request(:get,
                  "#{@endpoint}/room/#{room_id_or_name}/statistics",
                  "",
                  Client.headers(client),
                  Client.options(client, []))
  end

  @doc """
  [https://www.hipchat.com/docs/apiv2/method/invite_user](https://www.hipchat.com/docs/apiv2/method/invite_user)
  """
  @spec invite_user(Client.t, String.t, String.t, map) :: Httpc.res_t
  def invite_user(client, room_id_or_name, user_id_or_email, body) do
    Httpc.request(:post,
                  "#{@endpoint}/room/#{room_id_or_name}/invite/#{user_id_or_email}",
                  {:form, Map.to_list(body)},
                  Client.headers(client),
                  Client.options(client, []))
  end

  @doc """
  [https://www.hipchat.com/docs/apiv2/method/remove_member](https://www.hipchat.com/docs/apiv2/method/remove_member)
  """
  @spec remove_member(Client.t, String.t, String.t) :: Httpc.res_t
  def remove_member(client, room_id_or_name, user_id_or_email) do
    Httpc.request(:delete,
                  "#{@endpoint}/room/#{room_id_or_name}/member/#{user_id_or_email}",
                  "",
                  Client.headers(client),
                  Client.options(client, []))
  end

  @doc """
  [https://www.hipchat.com/docs/apiv2/method/reply_to_message](https://www.hipchat.com/docs/apiv2/method/reply_to_message)
  """
  @spec reply_to_message(Client.t, String.t, map) :: Httpc.res_t
  def reply_to_message(client, room_id_or_name, body) do
    Httpc.request(:post,
                  "#{@endpoint}/room/#{room_id_or_name}/reply",
                  {:form, Map.to_list(body)},
                  Client.headers(client),
                  Client.options(client, []))
  end

  @doc """
  [https://www.hipchat.com/docs/apiv2/method/send_message](https://www.hipchat.com/docs/apiv2/method/send_message)
  """
  @spec send_message(Client.t, String.t, map) :: Httpc.res_t
  def send_message(client, room_id_or_name, body) do
    Httpc.request(:post,
                  "#{@endpoint}/room/#{room_id_or_name}/message",
                  {:form, Map.to_list(body)},
                  Client.headers(client),
                  Client.options(client, []))
  end

  @doc """
  [https://www.hipchat.com/docs/apiv2/method/send_room_notification](https://www.hipchat.com/docs/apiv2/method/send_room_notification)
  """
  @spec send_room_notification(Client.t, String.t, map) :: Httpc.res_t
  def send_room_notification(client, room_id_or_name, body) do
    Httpc.request(:post,
                  "#{@endpoint}/room/#{room_id_or_name}/notification",
                  {:form, Map.to_list(body)},
                  Client.headers(client),
                  Client.options(client, []))
  end

  @doc """
  [https://www.hipchat.com/docs/apiv2/method/share_link_with_room](https://www.hipchat.com/docs/apiv2/method/share_link_with_room)
  """
  @spec share_link_with_room(Client.t, String.t, map) :: Httpc.res_t
  def share_link_with_room(client, room_id_or_name, body) do
    Httpc.request(:post,
                  "#{@endpoint}/room/#{room_id_or_name}/share/link",
                  {:form, Map.to_list(body)},
                  Client.headers(client),
                  Client.options(client, []))
  end

  @doc """
  [https://www.hipchat.com/docs/apiv2/method/update_room](https://www.hipchat.com/docs/apiv2/method/update_room)
  """
  @spec update_room(Client.t, String.t, map) :: Httpc.res_t
  def update_room(client, room_id_or_name, body) do
    Httpc.request(:put,
                  "#{@endpoint}/room/#{room_id_or_name}",
                  {:form, Map.to_list(body)},
                  Client.headers(client),
                  Client.options(client, []))
  end

  @doc """
  [https://www.hipchat.com/docs/apiv2/method/update_room_avatar](https://www.hipchat.com/docs/apiv2/method/update_room_avatar)
  """
  @spec update_room_avatar(Client.t, String.t, map) :: Httpc.res_t
  def update_room_avatar(client, room_id_or_name, body) do
    Httpc.request(:put,
                  "#{@endpoint}/room/#{room_id_or_name}/avatar",
                  {:form, Map.to_list(body)},
                  Client.headers(client),
                  Client.options(client, []))
  end
end

# Code generated by `$ mix hipchat.generate`
defmodule Hipchat.V2.Rooms do
  @moduledoc """
  HipChat V2 Rooms API module.
  """

  alias Hipchat.{Client, Httpc}

  @endpoint "https://api.hipchat.com/v2"

  @doc """
  [https://www.hipchat.com/docs/apiv2/method/send_room_notification](https://www.hipchat.com/docs/apiv2/method/send_room_notification)
  """
  @spec send_room_notification(Client.t, String.t, map) :: Httpc.res_t
  def send_room_notification(client, room_id_or_name, body) do
    Httpc.request(:post,
                  "#{@endpoint}/room/#{room_id_or_name}/notification",
                  {:form, Map.to_list(body)},
                  Client.headers(client),
                  Client.options(client, []))
  end
end


Unify assertion for context test case template (#2842)

The `create` test was matching on the struct inside the {:ok, %Thing{} = thing}
tuple, whereas the `update` test was matching in a separate assertion.
They now both match inside the `{:ok, %Thing{} = thing}` assertion.

  describe "<%= schema.plural %>" do
    alias <%= inspect schema.module %>

    @valid_attrs <%= inspect schema.params.create %>
    @update_attrs <%= inspect schema.params.update %>
    @invalid_attrs <%= inspect for {key, _} <- schema.params.create, into: %{}, do: {key, nil} %>

    def <%= schema.singular %>_fixture(attrs \\ %{}) do
      {:ok, <%= schema.singular %>} =
        attrs
        |> Enum.into(@valid_attrs)
        |> <%= inspect context.alias %>.create_<%= schema.singular %>()

      <%= schema.singular %>
    end

    test "list_<%= schema.plural %>/0 returns all <%= schema.plural %>" do
      <%= schema.singular %> = <%= schema.singular %>_fixture()
      assert <%= inspect context.alias %>.list_<%= schema.plural %>() == [<%= schema.singular %>]
    end

    test "get_<%= schema.singular %>!/1 returns the <%= schema.singular %> with given id" do
      <%= schema.singular %> = <%= schema.singular %>_fixture()
      assert <%= inspect context.alias %>.get_<%= schema.singular %>!(<%= schema.singular %>.id) == <%= schema.singular %>
    end

    test "create_<%= schema.singular %>/1 with valid data creates a <%= schema.singular %>" do
      assert {:ok, %<%= inspect schema.alias %>{} = <%= schema.singular %>} = <%= inspect context.alias %>.create_<%= schema.singular %>(@valid_attrs)<%= for {field, value} <- schema.params.create do %>
      assert <%= schema.singular %>.<%= field %> == <%= Mix.Phoenix.Schema.value(schema, field, value) %><% end %>
    end

    test "create_<%= schema.singular %>/1 with invalid data returns error changeset" do
      assert {:error, %Ecto.Changeset{}} = <%= inspect context.alias %>.create_<%= schema.singular %>(@invalid_attrs)
    end

    test "update_<%= schema.singular %>/2 with valid data updates the <%= schema.singular %>" do
      <%= schema.singular %> = <%= schema.singular %>_fixture()
      assert {:ok, %<%= inspect schema.alias %>{} = <%= schema.singular %>} = <%= inspect context.alias %>.update_<%= schema.singular %>(<%= schema.singular %>, @update_attrs)
      <%= for {field, value} <- schema.params.update do %>
      assert <%= schema.singular %>.<%= field %> == <%= Mix.Phoenix.Schema.value(schema, field, value) %><% end %>
    end

    test "update_<%= schema.singular %>/2 with invalid data returns error changeset" do
      <%= schema.singular %> = <%= schema.singular %>_fixture()
      assert {:error, %Ecto.Changeset{}} = <%= inspect context.alias %>.update_<%= schema.singular %>(<%= schema.singular %>, @invalid_attrs)
      assert <%= schema.singular %> == <%= inspect context.alias %>.get_<%= schema.singular %>!(<%= schema.singular %>.id)
    end

    test "delete_<%= schema.singular %>/1 deletes the <%= schema.singular %>" do
      <%= schema.singular %> = <%= schema.singular %>_fixture()
      assert {:ok, %<%= inspect schema.alias %>{}} = <%= inspect context.alias %>.delete_<%= schema.singular %>(<%= schema.singular %>)
      assert_raise Ecto.NoResultsError, fn -> <%= inspect context.alias %>.get_<%= schema.singular %>!(<%= schema.singular %>.id) end
    end

    test "change_<%= schema.singular %>/1 returns a <%= schema.singular %> changeset" do
      <%= schema.singular %> = <%= schema.singular %>_fixture()
      assert %Ecto.Changeset{} = <%= inspect context.alias %>.change_<%= schema.singular %>(<%= schema.singular %>)
    end
  end

  describe "<%= schema.plural %>" do
    alias <%= inspect schema.module %>

    @valid_attrs <%= inspect schema.params.create %>
    @update_attrs <%= inspect schema.params.update %>
    @invalid_attrs <%= inspect for {key, _} <- schema.params.create, into: %{}, do: {key, nil} %>

    def <%= schema.singular %>_fixture(attrs \\ %{}) do
      {:ok, <%= schema.singular %>} =
        attrs
        |> Enum.into(@valid_attrs)
        |> <%= inspect context.alias %>.create_<%= schema.singular %>()

      <%= schema.singular %>
    end

    test "list_<%= schema.plural %>/0 returns all <%= schema.plural %>" do
      <%= schema.singular %> = <%= schema.singular %>_fixture()
      assert <%= inspect context.alias %>.list_<%= schema.plural %>() == [<%= schema.singular %>]
    end

    test "get_<%= schema.singular %>!/1 returns the <%= schema.singular %> with given id" do
      <%= schema.singular %> = <%= schema.singular %>_fixture()
      assert <%= inspect context.alias %>.get_<%= schema.singular %>!(<%= schema.singular %>.id) == <%= schema.singular %>
    end

    test "create_<%= schema.singular %>/1 with valid data creates a <%= schema.singular %>" do
      assert {:ok, %<%= inspect schema.alias %>{} = <%= schema.singular %>} = <%= inspect context.alias %>.create_<%= schema.singular %>(@valid_attrs)<%= for {field, value} <- schema.params.create do %>
      assert <%= schema.singular %>.<%= field %> == <%= Mix.Phoenix.Schema.value(schema, field, value) %><% end %>
    end

    test "create_<%= schema.singular %>/1 with invalid data returns error changeset" do
      assert {:error, %Ecto.Changeset{}} = <%= inspect context.alias %>.create_<%= schema.singular %>(@invalid_attrs)
    end

    test "update_<%= schema.singular %>/2 with valid data updates the <%= schema.singular %>" do
      <%= schema.singular %> = <%= schema.singular %>_fixture()
      assert {:ok, <%= schema.singular %>} = <%= inspect context.alias %>.update_<%= schema.singular %>(<%= schema.singular %>, @update_attrs)
      assert %<%= inspect schema.alias %>{} = <%= schema.singular %><%= for {field, value} <- schema.params.update do %>
      assert <%= schema.singular %>.<%= field %> == <%= Mix.Phoenix.Schema.value(schema, field, value) %><% end %>
    end

    test "update_<%= schema.singular %>/2 with invalid data returns error changeset" do
      <%= schema.singular %> = <%= schema.singular %>_fixture()
      assert {:error, %Ecto.Changeset{}} = <%= inspect context.alias %>.update_<%= schema.singular %>(<%= schema.singular %>, @invalid_attrs)
      assert <%= schema.singular %> == <%= inspect context.alias %>.get_<%= schema.singular %>!(<%= schema.singular %>.id)
    end

    test "delete_<%= schema.singular %>/1 deletes the <%= schema.singular %>" do
      <%= schema.singular %> = <%= schema.singular %>_fixture()
      assert {:ok, %<%= inspect schema.alias %>{}} = <%= inspect context.alias %>.delete_<%= schema.singular %>(<%= schema.singular %>)
      assert_raise Ecto.NoResultsError, fn -> <%= inspect context.alias %>.get_<%= schema.singular %>!(<%= schema.singular %>.id) end
    end

    test "change_<%= schema.singular %>/1 returns a <%= schema.singular %> changeset" do
      <%= schema.singular %> = <%= schema.singular %>_fixture()
      assert %Ecto.Changeset{} = <%= inspect context.alias %>.change_<%= schema.singular %>(<%= schema.singular %>)
    end
  end


rebase

rebase

import HostTable
import Supervisor.Spec, warn: false

defmodule ExlasticLB do
  @moduledoc """
  """
  use Application

  @doc """
  """
  def starter(children, extra_opts \\ []) do
    # See http://elixir-lang.org/docs/stable/elixir/Application.html
    # for more information on OTP Applications
    unconditonal_children = [
      # Define workers and child supervisors to be supervised
    ]
    IO.puts("Children (#{Enum.count(children)} total): #{inspect(children)}")
    opts = extra_opts ++ [strategy: :one_for_one, name: ExlasticLB.Supervisor]
    Supervisor.start_link(
      unconditonal_children ++ children, opts)
  end

  @doc """
  """
  def start(start_type, [mix_env | start_args]) do
      HostTable.user_msg(
        "Application entry: #{inspect({mix_env, start_type, start_args})}")
      cond do
        is_atom(mix_env) ->
          sstart(mix_env, start_args)
        is_binary(mix_env) ->
          sstart(start_type, mix_env)
      end
  end
  # function-header, so no do/ends are needed
  def sstart(mix_env_or_mode, args \\ [])

  # function-clauses that work with pattern matching
  @doc """
  """
  def sstart(:test, []) do
      IO.puts("entry from 'mix test'?")
      starter([])
  end

  @doc """
  """
  def sstart(:dev, start_args) do
    Application.ensure_all_started(:quantum)
    Application.ensure_all_started(:erlcloud)
    starter(
      [supervisor(HostTable, start_args),
       supervisor(HostMon, [])])
  end

  @doc """
  """
  def sstart(:cli, config_file) do
    IO.puts("CLI entry: #{config_file}")
    sstart(:dev, [config_file])
  end
end

<<<<<<< HEAD
import HostTable
=======
>>>>>>> 35032fe... logging
import Supervisor.Spec, warn: false
require Logger

defmodule ExlasticLB do
  @moduledoc """
  """
  use Application

  @doc """
  """
  def starter(children, extra_opts \\ []) do
    # See http://elixir-lang.org/docs/stable/elixir/Application.html
    # for more information on OTP Applications
    unconditonal_children = [
      # Define workers and child supervisors to be supervised
    ]
    IO.puts("Children (#{Enum.count(children)} total): #{inspect(children)}")
    opts = extra_opts ++ [strategy: :one_for_one, name: ExlasticLB.Supervisor]
    Supervisor.start_link(
      unconditonal_children ++ children, opts)
  end

  @doc """
  """
  def start(start_type, [mix_env | start_args]) do
      HostTable.user_msg(
        "Application entry: #{inspect({mix_env, start_type, start_args})}")
      cond do
        is_atom(mix_env) ->
          sstart(mix_env, start_args)
        is_binary(mix_env) ->
          sstart(start_type, mix_env)
      end
  end
  # function-header, so no do/ends are needed
  def sstart(mix_env_or_mode, args \\ [])

  # function-clauses that work with pattern matching
  @doc """
  """
  def sstart(:test, []) do
      Logger.info("entry from 'mix test'?")
      starter([])
  end

  @doc """
  """
  def sstart(:dev, start_args) do
    Application.ensure_all_started(:quantum)
    Application.ensure_all_started(:erlcloud)
    starter(
      [supervisor(HostTable, start_args),
       supervisor(HostMon, [])])
  end

  @doc """
  """
  def sstart(:cli, config_file) do
    IO.puts("CLI entry: #{config_file}")
    sstart(:dev, [config_file])
  end
end