Rename state to emails

Rename state to emails

defmodule Swoosh.Adapters.Local.Storage.Memory do
  @moduledoc ~S"""
  In-memory storage driver used by the
  [Swoosh.Adapters.Local](Swoosh.Adapters.Local.html) module.

  The emails in this mailbox are stored in memory and won't persist once your
  application is stopped.
  """

  use GenServer

  @doc """
  Starts the server
  """
  def start_link() do
    GenServer.start_link(__MODULE__, [], name: __MODULE__)
  end

  @doc """
  Stops the server
  """
  def stop() do
    GenServer.stop(__MODULE__)
  end

  @doc ~S"""
  Push a new email into the mailbox.

  In order to make it easy to fetch a single email, a `Message-ID` header is
  added to the email before being stored.

  ## Examples

      iex> email = new |> from("tony.stark@example.com")
      %Swoosh.Email{from: {"", "tony.stark@example.com"}, [...]}
      iex> Memory.push(email)
      %Swoosh.Email{from: {"", "tony.stark@example.com"}, headers: %{"Message-ID": "a1b2c3"}, [...]}
  """
  def push(email) do
    GenServer.call(__MODULE__, {:push, email})
  end

  @doc ~S"""
  Pop the last email from the mailbox.

  ## Examples

      iex> email = new |> from("tony.stark@example.com")
      %Swoosh.Email{from: {"", "tony.stark@example.com"}, [...]}
      iex> Memory.push(email)
      %Swoosh.Email{from: {"", "tony.stark@example.com"}, headers: %{"Message-ID": "a1b2c3"}, [...]}
      iex> Memory.all() |> Enum.count()
      1
      iex> Memory.pop()
      %Swoosh.Email{from: {"", "tony.stark@example.com"}, headers: %{"Message-ID": "a1b2c3"}, [...]}
      iex> Memory.all() |> Enun.count()
      0
  """
  def pop() do
    GenServer.call(__MODULE__, :pop)
  end

  @doc ~S"""
  Get a specific email from the mailbox.

  ## Examples

      iex> email = new |> from("tony.stark@example.com")
      %Swoosh.Email{from: {"", "tony.stark@example.com"}, [...]}
      iex> Memory.push(email)
      %Swoosh.Email{from: {"", "tony.stark@example.com"}, headers: %{"Message-ID": "a1b2c3"}, [...]}
      iex> Memory.get("A1B2C3")
      %Swoosh.Email{from: {"", "tony.stark@example.com"}, headers: %{"Message-ID": "a1b2c3"}, [...]}
  """
  def get(id) do
    GenServer.call(__MODULE__, {:get, id})
  end

  @doc ~S"""
  List all the emails in the mailbox.

  ## Examples

      iex> email = new |> from("tony.stark@example.com")
      %Swoosh.Email{from: {"", "tony.stark@example.com"}, [...]}
      iex> Memory.push(email)
      %Swoosh.Email{from: {"", "tony.stark@example.com"}, headers: %{"Message-ID": "a1b2c3"}, [...]}
      iex> Memory.all()
      [%Swoosh.Email{from: {"", "tony.stark@example.com"}, headers: %{"Message-ID": "a1b2c3"}, [...]}]
  """
  def all() do
    GenServer.call(__MODULE__, :all)
  end

  @doc ~S"""
  Delete all the emails currently in the mailbox.

  ## Examples

      iex> email = new |> from("tony.stark@example.com")
      %Swoosh.Email{from: {"", "tony.stark@example.com"}, [...]}
      iex> Memory.push(email)
      %Swoosh.Email{from: {"", "tony.stark@example.com"}, headers: %{"Message-ID": "a1b2c3"}, [...]}
      iex> Memory.delete_all()
      :ok
      iex> Memory.list()
      []
  """
  def delete_all() do
    GenServer.call(__MODULE__, :delete_all)
  end

  # Callbacks

  def init(_args) do
    {:ok, []}
  end

  def handle_call({:push, email}, _from, emails) do
    id = :crypto.strong_rand_bytes(16) |> Base.encode16 |> String.downcase
    email = email |> Swoosh.Email.header("Message-ID", id)
    {:reply, email, [email | emails]}
  end

  def handle_call(:pop, _from, [h|t]) do
    {:reply, h, t}
  end

  def handle_call({:get, id}, _from, emails) do
    email = Enum.find(emails, fn %{headers: %{"Message-ID" => msg_id}} ->
      msg_id == String.downcase(id)
    end)
    {:reply, email, emails}
  end

  def handle_call(:all, _from, emails) do
    {:reply, emails, emails}
  end

  def handle_call(:delete_all, _from, _emails) do
    {:reply, :ok, []}
  end
end

defmodule Swoosh.Adapters.Local.Storage.Memory do
  @moduledoc ~S"""
  In-memory storage driver used by the
  [Swoosh.Adapters.Local](Swoosh.Adapters.Local.html) module.

  The emails in this mailbox are stored in memory and won't persist once your
  application is stopped.
  """

  use GenServer

  @doc """
  Starts the server
  """
  def start_link() do
    GenServer.start_link(__MODULE__, [], name: __MODULE__)
  end

  @doc """
  Stops the server
  """
  def stop() do
    GenServer.stop(__MODULE__)
  end

  @doc ~S"""
  Push a new email into the mailbox.

  In order to make it easy to fetch a single email, a `Message-ID` header is
  added to the email before being stored.

  ## Examples

      iex> email = new |> from("tony.stark@example.com")
      %Swoosh.Email{from: {"", "tony.stark@example.com"}, [...]}
      iex> Memory.push(email)
      %Swoosh.Email{from: {"", "tony.stark@example.com"}, headers: %{"Message-ID": "a1b2c3"}, [...]}
  """
  def push(email) do
    GenServer.call(__MODULE__, {:push, email})
  end

  @doc ~S"""
  Pop the last email from the mailbox.

  ## Examples

      iex> email = new |> from("tony.stark@example.com")
      %Swoosh.Email{from: {"", "tony.stark@example.com"}, [...]}
      iex> Memory.push(email)
      %Swoosh.Email{from: {"", "tony.stark@example.com"}, headers: %{"Message-ID": "a1b2c3"}, [...]}
      iex> Memory.all() |> Enum.count()
      1
      iex> Memory.pop()
      %Swoosh.Email{from: {"", "tony.stark@example.com"}, headers: %{"Message-ID": "a1b2c3"}, [...]}
      iex> Memory.all() |> Enun.count()
      0
  """
  def pop() do
    GenServer.call(__MODULE__, :pop)
  end

  @doc ~S"""
  Get a specific email from the mailbox.

  ## Examples

      iex> email = new |> from("tony.stark@example.com")
      %Swoosh.Email{from: {"", "tony.stark@example.com"}, [...]}
      iex> Memory.push(email)
      %Swoosh.Email{from: {"", "tony.stark@example.com"}, headers: %{"Message-ID": "a1b2c3"}, [...]}
      iex> Memory.get("A1B2C3")
      %Swoosh.Email{from: {"", "tony.stark@example.com"}, headers: %{"Message-ID": "a1b2c3"}, [...]}
  """
  def get(id) do
    GenServer.call(__MODULE__, {:get, id})
  end

  @doc ~S"""
  List all the emails in the mailbox.

  ## Examples

      iex> email = new |> from("tony.stark@example.com")
      %Swoosh.Email{from: {"", "tony.stark@example.com"}, [...]}
      iex> Memory.push(email)
      %Swoosh.Email{from: {"", "tony.stark@example.com"}, headers: %{"Message-ID": "a1b2c3"}, [...]}
      iex> Memory.all()
      [%Swoosh.Email{from: {"", "tony.stark@example.com"}, headers: %{"Message-ID": "a1b2c3"}, [...]}]
  """
  def all() do
    GenServer.call(__MODULE__, :all)
  end

  @doc ~S"""
  Delete all the emails currently in the mailbox.

  ## Examples

      iex> email = new |> from("tony.stark@example.com")
      %Swoosh.Email{from: {"", "tony.stark@example.com"}, [...]}
      iex> Memory.push(email)
      %Swoosh.Email{from: {"", "tony.stark@example.com"}, headers: %{"Message-ID": "a1b2c3"}, [...]}
      iex> Memory.delete_all()
      :ok
      iex> Memory.list()
      []
  """
  def delete_all() do
    GenServer.call(__MODULE__, :delete_all)
  end

  # Callbacks

  def init(_args) do
    {:ok, []}
  end

  def handle_call({:push, email}, _from, state) do
    id = :crypto.strong_rand_bytes(16) |> Base.encode16 |> String.downcase
    email = email |> Swoosh.Email.header("Message-ID", id)
    {:reply, email, [email] ++ state}
  end

  def handle_call(:pop, _from, [h|t]) do
    {:reply, h, t}
  end

  def handle_call({:get, id}, _from, state) do
    email = Enum.find(state, nil, fn %Swoosh.Email{headers: %{"Message-ID" => mid}} -> mid == String.downcase(id) end)
    {:reply, email, state}
  end

  def handle_call(:all, _from, state) do
    {:reply, state, state}
  end

  def handle_call(:delete_all, _from, _state) do
    {:reply, :ok, []}
  end
end


Improve docs for mix run

Improve docs for mix run

defmodule Mix.Tasks.Run do
  use Mix.Task

  @shortdoc "Runs the given file or expression"

  @moduledoc """
  Runs the given file or expression in the context of the application.

  You can use this task to execute a particular file or command:

      mix run -e Hello.world
      mix run my_script.exs

  This task provides a subset of the functionality available in the
  `elixir` executable, including setting up the `System.argv`:

      mix run my_script.exs arg1 arg2 arg3

  You can also use this task to simply start an application and keep
  it running without halting:

      mix run --no-halt

  Before running any command, the task compiles and starts the current
  application. Those can be configured with the options below.

  You may also pass option specific to the `elixir` executable as follows:

      elixir --sname hello -S mix run --no-halt

  ## Command line options

    * `--config`, `-c`  - loads the given configuration file
    * `--eval`, `-e` - evaluate the given code
    * `--require`, `-r` - require pattern before running the command
    * `--parallel-require`, `-pr` - requires pattern in parallel
    * `--no-compile` - do not compile even if files require compilation
    * `--no-deps-check` - do not check dependencies
    * `--no-halt` - do not halt the system after running the command
    * `--no-start` - do not start applications after compilation

  """

  @spec run(OptionParser.argv) :: :ok
  def run(args) do
    {opts, head, _} = OptionParser.parse_head(args,
      aliases: [r: :require, pr: :parallel_require, e: :eval, c: :config],
      switches: [parallel_require: :keep, require: :keep, eval: :keep, config: :keep,
                 halt: :boolean, compile: :boolean, deps_check: :boolean, start: :boolean])

    {file, argv} =
      case {Keyword.has_key?(opts, :eval), head} do
        {true, _}  -> {nil, head}
        {_, [h|t]} -> {h, t}
        {_, []}    -> {nil, []}
      end

    System.argv(argv)
    process_config opts

    # Start app after rewriting System.argv,
    # but before requiring and evaling
    Mix.Task.run "app.start", args
    process_load opts

    _ = if file do
      if File.regular?(file) do
        Code.require_file(file)
      else
        Mix.raise "No such file: #{file}"
      end
    end

    unless Keyword.get(opts, :halt, true), do: :timer.sleep(:infinity)
    :ok
  end

  defp process_config(opts) do
    Enum.each opts, fn
      {:config, value} ->
        Mix.Task.run "loadconfig", [value]
      _ ->
        :ok
    end
  end

  defp process_load(opts) do
    Enum.each opts, fn
      {:parallel_require, value} ->
        case filter_patterns(value) do
          [] ->
            Mix.raise "No files matched pattern #{inspect value} given to --parallel-require"
          filtered ->
            Kernel.ParallelRequire.files(filtered)
        end
      {:require, value} ->
        case filter_patterns(value) do
          [] ->
            Mix.raise "No files matched pattern #{inspect value} given to --require"
          filtered ->
            Enum.each(filtered, &Code.require_file(&1))
        end
      {:eval, value} ->
        Code.eval_string(value)
      _ ->
        :ok
    end
  end

  defp filter_patterns(pattern) do
    Enum.filter(Enum.uniq(Path.wildcard(pattern)), &File.regular?(&1))
  end
end

defmodule Mix.Tasks.Run do
  use Mix.Task

  @shortdoc "Run the given file or expression"

  @moduledoc """
  Runs the given file or expression in the context of the application.

  Before running the code, it invokes the `app.start` task which compiles
  and loads your project.

  It is the goal of this task to provide a subset of the functionality
  existent in the `elixir` executable, including setting up the `System.argv`:

      mix run -e Hello.world
      mix run my_script.exs arg1 arg2 arg3

  Many command line options need to be passed to the `elixir` executable
  directly, which can be done as follows:

      elixir --sname hello -S mix run -e "My.code"

  ## Command line options

    * `--config`, `-c`  - loads the given configuration file
    * `--eval`, `-e`    - evaluate the given code
    * `--require`, `-r` - require pattern before running the command
    * `--parallel-require`, `-pr`
                        - requires pattern in parallel
    * `--no-compile`    - do not compile even if files require compilation
    * `--no-deps-check` - do not check dependencies
    * `--no-halt`       - do not halt the system after running the command
    * `--no-start`      - do not start applications after compilation

  """

  @spec run(OptionParser.argv) :: :ok
  def run(args) do
    {opts, head, _} = OptionParser.parse_head(args,
      aliases: [r: :require, pr: :parallel_require, e: :eval, c: :config],
      switches: [parallel_require: :keep, require: :keep, eval: :keep, config: :keep,
                 halt: :boolean, compile: :boolean, deps_check: :boolean, start: :boolean])

    {file, argv} =
      case {Keyword.has_key?(opts, :eval), head} do
        {true, _}  -> {nil, head}
        {_, [h|t]} -> {h, t}
        {_, []}    -> {nil, []}
      end

    System.argv(argv)
    process_config opts

    # Start app after rewriting System.argv,
    # but before requiring and evaling
    Mix.Task.run "app.start", args
    process_load opts

    _ = if file do
      if File.regular?(file) do
        Code.require_file(file)
      else
        Mix.raise "No such file: #{file}"
      end
    end

    unless Keyword.get(opts, :halt, true), do: :timer.sleep(:infinity)
    :ok
  end

  defp process_config(opts) do
    Enum.each opts, fn
      {:config, value} ->
        Mix.Task.run "loadconfig", [value]
      _ ->
        :ok
    end
  end

  defp process_load(opts) do
    Enum.each opts, fn
      {:parallel_require, value} ->
        case filter_patterns(value) do
          [] ->
            Mix.raise "No files matched pattern #{inspect value} given to --parallel-require"
          filtered ->
            Kernel.ParallelRequire.files(filtered)
        end
      {:require, value} ->
        case filter_patterns(value) do
          [] ->
            Mix.raise "No files matched pattern #{inspect value} given to --require"
          filtered ->
            Enum.each(filtered, &Code.require_file(&1))
        end
      {:eval, value} ->
        Code.eval_string(value)
      _ ->
        :ok
    end
  end

  defp filter_patterns(pattern) do
    Enum.filter(Enum.uniq(Path.wildcard(pattern)), &File.regular?(&1))
  end
end


Fix firmware autodetector

Fix firmware autodetector

defmodule Farmbot.Firmware.UartHandler.AutoDetector do
  @moduledoc """
  Init module for configuring a UART handler. Here's what it does:

  * Enumerates Serial devices
  * Scrubs devices that should be ignored.
  * If there is *ONE* device:
    * Configures Farmbot.Behaviour.FirmwareHandler -> UartHandler
    * Configures the device to be used.
  * If there are zero or more than one device:
    * Configures Farmbot.Behaviour.FirmwareHandler -> StubHandler
  """

  alias Nerves.UART
  alias Farmbot.Firmware.{UartHandler, StubHandler}
  use Farmbot.Logger

  #TODO(Connor) - Maybe make this configurable?
  @ignore_devs ["ttyAMA0", "ttyS0", "ttyS3"]

  @doc "Autodetect relevent UART Devs."
  def auto_detect do
    UART.enumerate() |> Map.keys() |> Kernel.--(@ignore_devs)
  end

  @doc false
  def start_link(_, _) do
    GenServer.start_link(__MODULE__, [])
  end

  def init([]) do
    case auto_detect() do
      [dev] ->
        Logger.success 3, "detected target UART: #{dev}"
        update_fw_handler UartHandler
        Application.put_env(:farmbot, :uart_handler, tty: dev)
      _ ->
        Logger.error 1, "Could not detect a UART device."
        update_fw_handler StubHandler
    end
    :ignore
  end

  def update_fw_handler(fw_handler) do
    old = Application.get_all_env(:farmbot)[:behaviour]
    new = Keyword.put(old, :firmware_handler, fw_handler)
    Application.put_env(:farmbot, :behaviour, new)
  end

end

defmodule Farmbot.Firmware.UartHandler.AutoDetector do
  @moduledoc """
  Init module for configuring a UART handler. Here's what it does:

  * Enumerates Serial devices
  * Scrubs devices that should be ignored.
  * If there is *ONE* device:
    * Configures Farmbot.Behaviour.FirmwareHandler -> UartHandler
    * Configures the device to be used.
  * If there are zero or more than one device:
    * Configures Farmbot.Behaviour.FirmwareHandler -> StubHandler
  """

  alias Nerves.UART
  alias Farmbot.Firmware.{UartHandler, StubHandler}
  use Farmbot.Logger

  #TODO(Connor) - Maybe make this configurable?
  @ignore_devs ["ttyAMA0", "ttyS0", "ttyS3"]

  @doc "Autodetect relevent UART Devs."
  def auto_detect do
    UART.enumerate() |> Map.keys() |> Kernel.--(@ignore_devs)
  end

  @doc false
  def start_link(_, _) do
    GenServer.start_link(__MODULE__, [])
  end

  def init([]) do
    case auto_detect() do
      [dev] ->
        Logger.success 3, "detected target UART: #{dev}"
        update_fw_handler UartHandler
        Application.put_env(:farmbot, :uart_handler, tty: "/dev/ttyACM0")
      _ ->
        Logger.error 1, "Could not detect a UART device."
        update_fw_handler StubHandler
    end
    :ignore
  end

  def update_fw_handler(fw_handler) do
    old = Application.get_all_env(:farmbot)[:behaviour]
    new = Keyword.put(old, :firmware_handler, fw_handler)
    Application.put_env(:farmbot, :behaviour, new)
  end

end


add progress reporting to scenario outlines

defimpl WhiteBread.Runners, for: WhiteBread.Gherkin.Elements.ScenarioOutline do
  alias WhiteBread.Outputers.ProgressReporter

  def run(scenario_outline, context, setup) do
    scenario_outline
      |> build_each_example
      |> Enum.map(&WhiteBread.Runners.run(&1, context, setup))
      |> Enum.map(&process_result(&1, scenario_outline))
      |> report_progress(setup, scenario_outline)
  end

  defp process_result({:ok, _last_state}, scenario), do: {:ok, scenario.name}
  defp process_result(error_data,        _scenario), do: {:failed, error_data}

  defp build_each_example(outline) do
    outline.examples
      |> WhiteBread.Tables.index_table_by_first_row
      |> Enum.map(&create_steps(&1, outline.steps))
  end

  defp create_steps(example, step_outlines) do
    step_outlines
      |> Enum.map(&update_step_using_example(&1, example))
  end

  defp update_step_using_example(starting_step, example) do
    example
      |> Enum.reduce(starting_step, &replace_in_step/2)
  end

  defp replace_in_step({replace, with}, step) do
    %{text: initial} = step
    updated_text = initial
      |> String.replace("<#{to_string(replace)}>", with)
    %{step | text: updated_text}
  end

  defp report_progress(results, setup, scenario_outline) do
    failures? = results |> Enum.any?(fn {success, _} -> success != true end)
    success_status = if failures?, do: :failed, else: :ok
    scenario_report ={:scenario_result, {success_status, nil}, scenario_outline}
    setup.progress_reporter
      |> ProgressReporter.report(scenario_report)
    results
  end

end

defimpl WhiteBread.Runners, for: WhiteBread.Gherkin.Elements.ScenarioOutline do
  def run(scenario_outline, context, setup) do
    scenario_outline
      |> build_each_example
      |> Enum.map(&WhiteBread.Runners.run(&1, context, setup))
      |> Enum.map(&process_result(&1, scenario_outline))
  end

  defp process_result({:ok, _last_state}, scenario), do: {:ok, scenario.name}
  defp process_result(error_data,        _scenario), do: {:failed, error_data}

  defp build_each_example(outline) do
    outline.examples
      |> WhiteBread.Tables.index_table_by_first_row
      |> Enum.map(&create_steps(&1, outline.steps))
  end

  defp create_steps(example, step_outlines) do
    step_outlines
      |> Enum.map(&update_step_using_example(&1, example))
  end

  defp update_step_using_example(starting_step, example) do
    example
      |> Enum.reduce(starting_step, &replace_in_step/2)
  end

  defp replace_in_step({replace, with}, step) do
    %{text: initial} = step
    updated_text = initial
      |> String.replace("<#{to_string(replace)}>", with)
    %{step | text: updated_text}
  end

end


Enable favicon as a static asset.

Enable favicon as a static asset.

defmodule SlackCoder.Endpoint do
  use Phoenix.Endpoint, otp_app: :slack_coder

  socket "/socket", SlackCoder.UserSocket

  # Serve at "/" the static files from "priv/static" directory.
  #
  # You should set gzip to true if you are running phoenix.digest
  # when deploying your static files in production.
  plug Plug.Static,
    at: "/", from: :slack_coder, gzip: false,
    only: ~w(css fonts images js favicon.png robots.txt)

  # Code reloading can be explicitly enabled under the
  # :code_reloader configuration of your endpoint.
  if code_reloading? do
    socket "/phoenix/live_reload/socket", Phoenix.LiveReloader.Socket
    plug Phoenix.LiveReloader
    plug Phoenix.CodeReloader
  end

  plug Plug.RequestId
  plug Plug.Logger

  plug Plug.Parsers,
    parsers: [:urlencoded, :multipart, :json],
    pass: ["*/*"],
    json_decoder: Poison

  plug Plug.MethodOverride
  plug Plug.Head

  plug Plug.Session,
    store: :cookie,
    key: "_slack_coder_key",
    signing_salt: "rPDcc861"

  plug SlackCoder.Router
end

defmodule SlackCoder.Endpoint do
  use Phoenix.Endpoint, otp_app: :slack_coder

  socket "/socket", SlackCoder.UserSocket

  # Serve at "/" the static files from "priv/static" directory.
  #
  # You should set gzip to true if you are running phoenix.digest
  # when deploying your static files in production.
  plug Plug.Static,
    at: "/", from: :slack_coder, gzip: false,
    only: ~w(css fonts images js favicon.ico robots.txt)

  # Code reloading can be explicitly enabled under the
  # :code_reloader configuration of your endpoint.
  if code_reloading? do
    socket "/phoenix/live_reload/socket", Phoenix.LiveReloader.Socket
    plug Phoenix.LiveReloader
    plug Phoenix.CodeReloader
  end

  plug Plug.RequestId
  plug Plug.Logger

  plug Plug.Parsers,
    parsers: [:urlencoded, :multipart, :json],
    pass: ["*/*"],
    json_decoder: Poison

  plug Plug.MethodOverride
  plug Plug.Head

  plug Plug.Session,
    store: :cookie,
    key: "_slack_coder_key",
    signing_salt: "rPDcc861"

  plug SlackCoder.Router
end


Do not encode the changeset for errors

Do not encode the changeset for errors

Instead use new Ecto.Changeset.traverse_errors.

defmodule <%= base %>.ChangesetView do
  use <%= base %>.Web, :view

  @doc """
  Traverses and translates changeset errors.

  See `Ecto.Changeset.traverse_errors/2` for more details.`
  """
  def translate_errors(changeset) do
    Ecto.Changeset.traverse_errors(changeset, &translate_error(&1))
  end

  def render("error.json", %{changeset: changeset}) do
    # When encoded, the changeset returns its errors
    # as a JSON object. So we just pass it forward.
    %{errors: translate_errors(changeset)}
  end
end

defmodule <%= base %>.ChangesetView do
  use <%= base %>.Web, :view

  def render("error.json", %{changeset: changeset}) do
    # When encoded, the changeset returns its errors
    # as a JSON object. So we just pass it forward.
    %{errors: changeset}
  end
end


Delete data key from user render.

Delete data key from user render.

defmodule Goncord.UserView do
  use Goncord.Web, :view

  def render("index.json", %{users: users}) do
    render_many(users, Goncord.UserView, "user.json")
  end

  def render("show.json", %{user: user}) do
    render_one(user, Goncord.UserView, "user.json")
  end

  def render("user.json", %{user: user}) do
    %{login: user.login,
      email: user.email,
      first_name: user.first_name,
      last_name: user.last_name,
      second_name: user.second_name,
      birthday: user.birthday}
  end
end

defmodule Goncord.UserView do
  use Goncord.Web, :view

  def render("index.json", %{users: users}) do
    %{data: render_many(users, Goncord.UserView, "user.json")}
  end

  def render("show.json", %{user: user}) do
    %{data: render_one(user, Goncord.UserView, "user.json")}
  end

  def render("user.json", %{user: user}) do
    %{login: user.login,
      email: user.email,
      first_name: user.first_name,
      last_name: user.last_name,
      second_name: user.second_name,
      birthday: user.birthday}
  end
end


Fix target/source swap when generating firmware patches

Fixes #579

defmodule Mix.Tasks.Firmware.Patch do
  use Mix.Task
  import Mix.Nerves.Utils
  alias Nerves.Utils.Shell
  alias Mix.Nerves.Preflight

  @shortdoc "Build a firmware patch"

  @fwup_semver "~> 1.6 or ~> 1.6.0-dev"

  @moduledoc """
  Generate a firmware patch from a source and target firmware and output a new
  firmware file with the patch contents. The source firmware file

  This requires fwup >= 1.6.0

  ## Command line options

    * `--source` - (Optional) The path to the .fw file used as the source.
      Defaults to the last firmware built.
    * `--target` - (Optional) The path to the .fw file used as the target.
      Defaults to generating a new firmware without overwriting the source.
    * `--output` - (Optional) The path to the .fw file used to write the patch
      firmware. Defaults to `Nerves.Env.firmware_path/1`
  """

  @switches [source: :string, target: :string, output: :string]

  @impl true
  def run(args) do
    work_dir = Path.join(Nerves.Env.images_path(), "patch")
    File.rm_rf!(work_dir)
    File.mkdir_p!(work_dir)

    config = Mix.Project.config()
    {opts, _, _} = OptionParser.parse(args, switches: @switches)

    Preflight.ensure_fwup_version!("fwup", @fwup_semver)

    source = (opts[:source] || Nerves.Env.firmware_path(config)) |> Path.expand()

    unless File.exists?(source) do
      Mix.raise("""
      Source firmware #{source} does not exist.
      Please pass --source /path/source.fw or run `mix firmware`.
      """)
    end

    source_stats = File.stat!(source)

    target = (opts[:target] || mix_target_firmware(work_dir)) |> Path.expand()
    output = (opts[:output] || Path.join(Nerves.Env.images_path(), "patch.fw")) |> Path.expand()

    Shell.info("""
    Generating patch firmware
    """)

    target_stats = File.stat!(target)

    source_work_dir = Path.join(work_dir, "source")
    target_work_dir = Path.join(work_dir, "target")
    output_work_dir = Path.join(work_dir, "output")

    File.mkdir_p!(source_work_dir)
    File.mkdir_p!(target_work_dir)
    File.mkdir_p!(Path.join(output_work_dir, "data"))

    {_, 0} = shell("unzip", ["-qq", source, "-d", source_work_dir])
    {_, 0} = shell("unzip", ["-qq", target, "-d", target_work_dir])

    source_rootfs = Path.join([source_work_dir, "data", "rootfs.img"])
    target_rootfs = Path.join([target_work_dir, "data", "rootfs.img"])
    out_rootfs = Path.join([output_work_dir, "data", "rootfs.img"])

    {_, 0} = shell("xdelta3", ["-A", "-S", "-f", "-s", source_rootfs, target_rootfs, out_rootfs])

    File.mkdir_p!(Path.dirname(output))
    File.cp!(target, output)

    {_, 0} = shell("zip", ["-qq", output, "data/rootfs.img"], cd: output_work_dir)

    output_stats = File.stat!(output)

    {source_meta, 0} = System.cmd("fwup", ["-m", "-i", source])
    {target_meta, 0} = System.cmd("fwup", ["-m", "-i", target])

    [source_uuid | _] = String.split(source_meta, "meta-uuid=") |> Enum.reverse()
    [target_uuid | _] = String.split(target_meta, "meta-uuid=") |> Enum.reverse()

    source_uuid = String.trim(source_uuid, "\"")
    target_uuid = String.trim(target_uuid, "\"")

    File.rm_rf!(work_dir)

    Shell.success("""

    Finished generating patch firmware

    Source
    #{source}
    uuid: #{source_uuid}
    size: #{source_stats.size} bytes

    Target
    #{target}
    uuid: #{target_uuid}
    size: #{target_stats.size} bytes

    Patch
    #{output}
    size: #{output_stats.size} bytes
    """)
  end

  defp mix_target_firmware(work_dir) do
    Shell.info("Generating new target firmware")
    out_fw = Path.join(work_dir, "target.fw")
    Mix.Tasks.Firmware.run(["--output", out_fw])
    out_fw
  end
end

defmodule Mix.Tasks.Firmware.Patch do
  use Mix.Task
  import Mix.Nerves.Utils
  alias Nerves.Utils.Shell
  alias Mix.Nerves.Preflight

  @shortdoc "Build a firmware patch"

  @fwup_semver "~> 1.6 or ~> 1.6.0-dev"

  @moduledoc """
  Generate a firmware patch from a source and target firmware and output a new
  firmware file with the patch contents. The source firmware file

  This requires fwup >= 1.6.0

  ## Command line options

    * `--source` - (Optional) The path to the .fw file used as the source.
      Defaults to the last firmware built.
    * `--target` - (Optional) The path to the .fw file used as the target.
      Defaults to generating a new firmware without overwriting the source.
    * `--output` - (Optional) The path to the .fw file used to write the patch
      firmware. Defaults to `Nerves.Env.firmware_path/1`
  """

  @switches [source: :string, target: :string, output: :string]

  @impl true
  def run(args) do
    work_dir = Path.join(Nerves.Env.images_path(), "patch")
    File.rm_rf!(work_dir)
    File.mkdir_p!(work_dir)

    config = Mix.Project.config()
    {opts, _, _} = OptionParser.parse(args, switches: @switches)

    Preflight.ensure_fwup_version!("fwup", @fwup_semver)

    source = (opts[:source] || Nerves.Env.firmware_path(config)) |> Path.expand()

    unless File.exists?(source) do
      Mix.raise("""
      Source firmware #{source} does not exist.
      Please pass --source /path/source.fw or run `mix firmware`.
      """)
    end

    source_stats = File.stat!(source)

    target = (opts[:target] || mix_target_firmware(work_dir)) |> Path.expand()
    output = (opts[:output] || Path.join(Nerves.Env.images_path(), "patch.fw")) |> Path.expand()

    Shell.info("""
    Generating patch firmware
    """)

    target_stats = File.stat!(target)

    source_work_dir = Path.join(work_dir, "source")
    target_work_dir = Path.join(work_dir, "target")
    output_work_dir = Path.join(work_dir, "output")

    File.mkdir_p!(source_work_dir)
    File.mkdir_p!(target_work_dir)
    File.mkdir_p!(Path.join(output_work_dir, "data"))

    {_, 0} = shell("unzip", ["-qq", source, "-d", source_work_dir])
    {_, 0} = shell("unzip", ["-qq", target, "-d", target_work_dir])

    source_rootfs = Path.join([source_work_dir, "data", "rootfs.img"])
    target_rootfs = Path.join([target_work_dir, "data", "rootfs.img"])
    out_rootfs = Path.join([output_work_dir, "data", "rootfs.img"])

    {_, 0} = shell("xdelta3", ["-A", "-S", "-f", "-s", source_rootfs, target_rootfs, out_rootfs])

    File.mkdir_p!(Path.dirname(output))
    File.cp!(source, output)

    {_, 0} = shell("zip", ["-qq", output, "data/rootfs.img"], cd: output_work_dir)

    output_stats = File.stat!(output)

    {source_meta, 0} = System.cmd("fwup", ["-m", "-i", source])
    {target_meta, 0} = System.cmd("fwup", ["-m", "-i", target])

    [source_uuid | _] = String.split(source_meta, "meta-uuid=") |> Enum.reverse()
    [target_uuid | _] = String.split(target_meta, "meta-uuid=") |> Enum.reverse()

    source_uuid = String.trim(source_uuid, "\"")
    target_uuid = String.trim(target_uuid, "\"")

    File.rm_rf!(work_dir)

    Shell.success("""

    Finished generating patch firmware

    Source
    #{source}
    uuid: #{source_uuid}
    size: #{source_stats.size} bytes

    Target
    #{target}
    uuid: #{target_uuid}
    size: #{target_stats.size} bytes

    Patch
    #{output}
    size: #{output_stats.size} bytes
    """)
  end

  defp mix_target_firmware(work_dir) do
    Shell.info("Generating new target firmware")
    out_fw = Path.join(work_dir, "target.fw")
    Mix.Tasks.Firmware.run(["--output", out_fw])
    out_fw
  end
end