Spell out timeout default for websockets

defmodule Phoenix.Transports.WebSocket do
  @moduledoc """
  Socket transport for websocket clients.

  ## Configuration

  The websocket is configurable in your socket:

      transport :websocket, Phoenix.Transports.WebSocket,
        timeout: :infinity,
        serializer: Phoenix.Transports.WebSocketSerializer,
        transport_log: false

    * `:timeout` - the timeout for keeping websocket connections
      open after it last received data, defaults to 60_000ms

    * `:transport_log` - if the transport layer itself should log and, if so, the level

    * `:serializer` - the serializer for websocket messages

    * `:check_origin` - if we should check the origin of requests when the
      origin header is present. It defaults to true and, in such cases,
      it will check against the host value in `YourApp.Endpoint.config(:url)[:host]`.
      It may be set to `false` (not recommended) or to a list of explicitly
      allowed origins

    * `:code_reloader` - optionally override the default `:code_reloader` value
      from the socket's endpoint

  ## Serializer

  By default, JSON encoding is used to broker messages to and from clients.
  A custom serializer may be given as module which implements the `encode!/1`
  and `decode!/2` functions defined by the `Phoenix.Transports.Serializer`
  behaviour.

  The `encode!/1` function must return a tuple in the format
  `{:socket_push, :text | :binary, String.t | binary}`.
  """

  @behaviour Phoenix.Socket.Transport

  def default_config() do
    [serializer: Phoenix.Transports.WebSocketSerializer,
     timeout: 60_000,
     transport_log: false]
  end

  def handlers() do
    %{cowboy: Phoenix.Endpoint.CowboyWebSocket}
  end

  ## Callbacks

  import Plug.Conn, only: [fetch_query_params: 1, send_resp: 3]

  alias Phoenix.Socket.Broadcast
  alias Phoenix.Socket.Transport

  @doc false
  def init(%Plug.Conn{method: "GET"} = conn, {endpoint, handler, transport}) do
    {_, opts} = handler.__transport__(transport)

    conn =
      conn
      |> code_reload(opts, endpoint)
      |> Plug.Conn.fetch_query_params
      |> Transport.transport_log(opts[:transport_log])
      |> Transport.force_ssl(handler, endpoint, opts)
      |> Transport.check_origin(handler, endpoint, opts)

    case conn do
      %{halted: false} = conn ->
        params     = conn.params
        serializer = Keyword.fetch!(opts, :serializer)

        case Transport.connect(endpoint, handler, transport, __MODULE__, serializer, params) do
          {:ok, socket} ->
            {:ok, conn, {__MODULE__, {socket, opts}}}
          :error ->
            send_resp(conn, 403, "")
            {:error, conn}
        end
      %{halted: true} = conn ->
        {:error, conn}
    end
  end

  def init(conn, _) do
    send_resp(conn, :bad_request, "")
    {:error, conn}
  end

  @doc false
  def ws_init({socket, config}) do
    Process.flag(:trap_exit, true)
    serializer = Keyword.fetch!(config, :serializer)
    timeout    = Keyword.fetch!(config, :timeout)

    if socket.id, do: socket.endpoint.subscribe(self, socket.id, link: true)

    {:ok, %{socket: socket,
            channels: HashDict.new,
            channels_inverse: HashDict.new,
            serializer: serializer}, timeout}
  end

  @doc false
  def ws_handle(opcode, payload, state) do
    msg   = state.serializer.decode!(payload, opcode: opcode)

    case Transport.dispatch(msg, state.channels, state.socket) do
      :noreply ->
        {:ok, state}
      {:reply, reply_msg} ->
        encode_reply(reply_msg, state)
      {:joined, channel_pid, reply_msg} ->
        encode_reply(reply_msg, put(state, msg.topic, channel_pid))
      {:error, _reason, error_reply_msg} ->
        encode_reply(error_reply_msg, state)
    end
  end

  @doc false
  def ws_info({:EXIT, channel_pid, reason}, state) do
    case HashDict.get(state.channels_inverse, channel_pid) do
      nil   -> {:ok, state}
      topic ->
        new_state = delete(state, topic, channel_pid)
        encode_reply Transport.on_exit_message(topic, reason), new_state
    end
  end

  @doc false
  def ws_info(%Broadcast{event: "disconnect"}, state) do
    {:shutdown, state}
  end

  def ws_info({:socket_push, _, _encoded_payload} = msg, state) do
    format_reply(msg, state)
  end

  def ws_info(_, state) do
    {:ok, state}
  end

  @doc false
  def ws_terminate(_reason, _state) do
    :ok
  end

  @doc false
  def ws_close(state) do
    for {pid, _} <- state.channels_inverse do
      Phoenix.Channel.Server.close(pid)
    end
  end

  defp put(state, topic, channel_pid) do
    %{state | channels: HashDict.put(state.channels, topic, channel_pid),
              channels_inverse: HashDict.put(state.channels_inverse, channel_pid, topic)}
  end

  defp delete(state, topic, channel_pid) do
    %{state | channels: HashDict.delete(state.channels, topic),
              channels_inverse: HashDict.delete(state.channels_inverse, channel_pid)}
  end

  defp encode_reply(reply, state) do
    format_reply(state.serializer.encode!(reply), state)
  end

  defp format_reply({:socket_push, encoding, encoded_payload}, state) do
    {:reply, {encoding, encoded_payload}, state}
  end

  defp code_reload(conn, opts, endpoint) do
    reload? = Keyword.get(opts, :code_reloader, endpoint.config(:code_reloader))
    if reload?, do: Phoenix.CodeReloader.reload!(endpoint)

    conn
  end
end

defmodule Phoenix.Transports.WebSocket do
  @moduledoc """
  Socket transport for websocket clients.

  ## Configuration

  The websocket is configurable in your socket:

      transport :websocket, Phoenix.Transports.WebSocket,
        timeout: :infinity,
        serializer: Phoenix.Transports.WebSocketSerializer,
        transport_log: false

    * `:timeout` - the timeout for keeping websocket connections
      open after it last received data

    * `:transport_log` - if the transport layer itself should log and, if so, the level

    * `:serializer` - the serializer for websocket messages

    * `:check_origin` - if we should check the origin of requests when the
      origin header is present. It defaults to true and, in such cases,
      it will check against the host value in `YourApp.Endpoint.config(:url)[:host]`.
      It may be set to `false` (not recommended) or to a list of explicitly
      allowed origins

    * `:code_reloader` - optionally override the default `:code_reloader` value
      from the socket's endpoint

  ## Serializer

  By default, JSON encoding is used to broker messages to and from clients.
  A custom serializer may be given as module which implements the `encode!/1`
  and `decode!/2` functions defined by the `Phoenix.Transports.Serializer`
  behaviour.

  The `encode!/1` function must return a tuple in the format
  `{:socket_push, :text | :binary, String.t | binary}`.
  """

  @behaviour Phoenix.Socket.Transport

  def default_config() do
    [serializer: Phoenix.Transports.WebSocketSerializer,
     timeout: 60_000,
     transport_log: false]
  end

  def handlers() do
    %{cowboy: Phoenix.Endpoint.CowboyWebSocket}
  end

  ## Callbacks

  import Plug.Conn, only: [fetch_query_params: 1, send_resp: 3]

  alias Phoenix.Socket.Broadcast
  alias Phoenix.Socket.Transport

  @doc false
  def init(%Plug.Conn{method: "GET"} = conn, {endpoint, handler, transport}) do
    {_, opts} = handler.__transport__(transport)

    conn =
      conn
      |> code_reload(opts, endpoint)
      |> Plug.Conn.fetch_query_params
      |> Transport.transport_log(opts[:transport_log])
      |> Transport.force_ssl(handler, endpoint, opts)
      |> Transport.check_origin(handler, endpoint, opts)

    case conn do
      %{halted: false} = conn ->
        params     = conn.params
        serializer = Keyword.fetch!(opts, :serializer)

        case Transport.connect(endpoint, handler, transport, __MODULE__, serializer, params) do
          {:ok, socket} ->
            {:ok, conn, {__MODULE__, {socket, opts}}}
          :error ->
            send_resp(conn, 403, "")
            {:error, conn}
        end
      %{halted: true} = conn ->
        {:error, conn}
    end
  end

  def init(conn, _) do
    send_resp(conn, :bad_request, "")
    {:error, conn}
  end

  @doc false
  def ws_init({socket, config}) do
    Process.flag(:trap_exit, true)
    serializer = Keyword.fetch!(config, :serializer)
    timeout    = Keyword.fetch!(config, :timeout)

    if socket.id, do: socket.endpoint.subscribe(self, socket.id, link: true)

    {:ok, %{socket: socket,
            channels: HashDict.new,
            channels_inverse: HashDict.new,
            serializer: serializer}, timeout}
  end

  @doc false
  def ws_handle(opcode, payload, state) do
    msg   = state.serializer.decode!(payload, opcode: opcode)

    case Transport.dispatch(msg, state.channels, state.socket) do
      :noreply ->
        {:ok, state}
      {:reply, reply_msg} ->
        encode_reply(reply_msg, state)
      {:joined, channel_pid, reply_msg} ->
        encode_reply(reply_msg, put(state, msg.topic, channel_pid))
      {:error, _reason, error_reply_msg} ->
        encode_reply(error_reply_msg, state)
    end
  end

  @doc false
  def ws_info({:EXIT, channel_pid, reason}, state) do
    case HashDict.get(state.channels_inverse, channel_pid) do
      nil   -> {:ok, state}
      topic ->
        new_state = delete(state, topic, channel_pid)
        encode_reply Transport.on_exit_message(topic, reason), new_state
    end
  end

  @doc false
  def ws_info(%Broadcast{event: "disconnect"}, state) do
    {:shutdown, state}
  end

  def ws_info({:socket_push, _, _encoded_payload} = msg, state) do
    format_reply(msg, state)
  end

  def ws_info(_, state) do
    {:ok, state}
  end

  @doc false
  def ws_terminate(_reason, _state) do
    :ok
  end

  @doc false
  def ws_close(state) do
    for {pid, _} <- state.channels_inverse do
      Phoenix.Channel.Server.close(pid)
    end
  end

  defp put(state, topic, channel_pid) do
    %{state | channels: HashDict.put(state.channels, topic, channel_pid),
              channels_inverse: HashDict.put(state.channels_inverse, channel_pid, topic)}
  end

  defp delete(state, topic, channel_pid) do
    %{state | channels: HashDict.delete(state.channels, topic),
              channels_inverse: HashDict.delete(state.channels_inverse, channel_pid)}
  end

  defp encode_reply(reply, state) do
    format_reply(state.serializer.encode!(reply), state)
  end

  defp format_reply({:socket_push, encoding, encoded_payload}, state) do
    {:reply, {encoding, encoded_payload}, state}
  end

  defp code_reload(conn, opts, endpoint) do
    reload? = Keyword.get(opts, :code_reloader, endpoint.config(:code_reloader))
    if reload?, do: Phoenix.CodeReloader.reload!(endpoint)

    conn
  end
end


Add struct for use in other apps

Add struct for use in other apps

Struct representing the available metadata for a file pulled in by the
web scraper.

defmodule FileProcessor.FileMetadata do
  defstruct name: "", department: "", title: "", date_published: :nil, source_url: "", file_type: :nil, filename: "", year: :nil, data_type: :nil
end

error: pathspec 'src/elixir/data_processor/apps/file_processor/lib/file_processor/file_metadata.ex' did not match any file(s) known to git


RewriteRule (.*) index.php%{REQUEST_URI} [L] This correctly handles the GET parameters tacked onto requests.

fatal: unable to access 'https://github.com/nicholasryan/CorePlus.git/': The requested URL returned error: 403


Add color text functions

Add color text functions

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/joshforisha/merchant-quest.git/'


Add a MarcoPolo.RID struct

Add a MarcoPolo.RID struct

The `MarcoPolo.RID` module defines a struct that will represent record
ids. It will be used both to encode/decode the LINK type as well as to
provide some convenience functions (like `RID.parse_string("#0:1")`).

defmodule MarcoPolo.RID do
  defstruct [:cluster_id, :position]
end

error: pathspec 'lib/marco_polo/rid.ex' did not match any file(s) known to git


SMPP session draft

SMPP session draft

defmodule SMPPEX.Session do

  alias SMPPEX.Session
  alias SMPPEX.TCP.Connection
  alias SMPPEX.Pdu
  alias SMPPEX.Protocol

  defstruct connection: nil, smpp_handler: nil, buffer: <<>>

  @spec new(port, any, list) :: pid

  def new(socket, smpp_handler, connection_opts \\ []) do
    session = %Session{ smpp_handler: smpp_handler }
    {:ok, pid} = Connection.start_link(socket, session, connection_opts)
    pid
  end

  @type send_result :: :ok | {:error, any}

  @spec send(pid, Pdu.t) :: send_result
  def send(pid, pdu) do
    case Protocol.build(pdu) do
      {:ok, bin_pdu} ->
        case Connection.send(pid, bin_pdu) do
          :ok -> :ok
          :error -> {:error, "Connection error"}
        end
      {:error, _} = err -> err
    end
  end

  @spec close(pid) :: :ok
  def close(pid), do: Connection.close(pid)

end

defimpl SMPPEX.TCP.ConnectionHandler, for: SMPPEX.Session do

  alias SMPPEX.Session
  alias SMPPEX.Protocol

  require Logger

  def handle_connected(handler, connection) do
    log(handler, :debug, "established")
    smpp_handler = SMPPHandler.handle_connected(connection)
    %Session{ handler | connection: connection, smpp_handler: smpp_handler }
  end

  def handle_data_received(handler, data) do
    log(handler, :debug, "data received: #{inspect data}")
    buffer = handler.buffer <> data
    case process_packets(handler, buffer) do
      {:ok, new_buffer} -> {:ok, %Session{ handler | buffer: new_buffer } }
      {:error, _} = err -> err
    end
  end

  def handle_data_sent(handler, data) do
    log(handler, :debug, "data sent: #{inspect data}")
  end

  def handle_peer_closed(handler) do
    log(handler, :info, "closed remotely")
    SMPPHandler.handle_peer_closed(handler.smpp_handler)
  end

  def handle_closed(handler) do
    log(handler, :info, "closed")
    SMPPHandler.handle_closed(handler.smpp_handler)
  end

  def handle_error_closed(handler, error) do
    log(handler, :info, "closed due to tcp error: #{inspect error}")
    SMPPHandler.handle_error_closed(handler.smpp_handler, error)
  end

  defp process_packets(handler, data) do
    case Protocol.parse(data) do
      {:ok, nil, rest} -> {:ok, rest}
      {:ok, parse_result, rest} ->
        handle_parse_result(handler, parse_result)
        process_packets(handler, rest)
      {:error, _} = err ->
        log(handler, :warn, "incoming SMPP packet parsing error: #{inspect err}, initiating connection close")
        err
    end
  end

  defp log(handler, level, message) do
    Logger.log(level, "Session #{inspect handler.connection} #{message}")
  end

  defp handle_parse_result(handler, {:pdu, pdu}) do
    log(handler, :debug, "packet received: #{inspect pdu}")
    SMPPHandler.handle_pdu(handler.smpp_handler, pdu)
  end

  defp handle_parse_result(handler, {:unparsed_pdu, pdu, error}) do
    log(handler, :debug, "malformed packet received: #{inspect pdu}")
    SMPPHandler.handle_unparsed_pdu(handler.smpp_handler, pdu, error)
  end

end

error: pathspec 'lib/smppex/session.ex' did not match any file(s) known to git


fix test transactions for model tests

fix test transactions for model tests

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/evercam/evercam-media.git/'


feat(role_checker): add model

feat(role_checker): add model

defmodule Lyn.RoleChecker do
  alias Lyn.Repo
  alias Lyn.Role

  def is_admin?(user) do
    (role = Repo.get(Role, user.role_id)) && role.admin
  end
end

error: pathspec 'web/models/role_checker.ex' did not match any file(s) known to git


Fix get env during debug (#4030)

Fix get env during debug (#4030)

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/edenlabllc/ehealth.api.git/'


Task supervisor: run acceptors

Task supervisor: run acceptors

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/sharkspeed/dororis.git/'


[patch] fix speciality migration (#2041)


Hello world elixir

Hello world elixir

error: pathspec 'try-elixir/hello-world.ex' did not match any file(s) known to git


add snake_start_length to game_form table

defmodule BsRepo.Migrations.AddSnakeStartLengthToGameForm do
  use Ecto.Migration

  def change do
    alter table(BsRepo.GameForm) do
      add :snake_start_length, :any
    end
  end
end

error: pathspec 'priv/bs_repo/migrations/20180118023853_add_snake_start_length_to_game_form.exs' did not match any file(s) known to git


Add hash index cache

Add hash index cache

defmodule Survey.Repo.Migrations.WikiIndexChange do
  use Ecto.Migration

  def change do
    drop index(:cache, [:blob], unique: false)
    execute("create index on cache using hash(blob)")
  end
end

error: pathspec 'priv/repo/migrations/20150720042519_wiki_index_change.exs' did not match any file(s) known to git


Create 1.exs

Create 1.exs

defmodule Vec, do: defstruct x: 0, y: 0

defimpl String.Chars, for: Vec do
    def to_string(v), do: "{#{v.x}, #{v.y}}"
end

defimpl Inspect, for: Vec do
    def inspect(v, _), do: to_string(v)
end

defmodule App do

    @origin %Vec{}

    @n %Vec{y: 1}
    @s %Vec{y: -1}
    @e %Vec{x: 1}
    @w %Vec{x: -1}

    def turnVector(@n,  "R"), do: @e
    def turnVector(@e,  "R"), do: @s
    def turnVector(@s,  "R"), do: @w
    def turnVector(@w,  "R"), do: @n
    def turnVector(@n,  "L"), do: @w
    def turnVector(@e,  "L"), do: @n
    def turnVector(@s,  "L"), do: @e
    def turnVector(@w,  "L"), do: @s

    def parseMoveList(input) do
        String.split(input, ", ")
        # Now we have something like [RL]\d{1,3}
        |> Enum.map(
            fn(s) ->
            %{
                turnDirection: String.first(s),
                distance: elem(Integer.parse(String.slice(s, 1..-1)), 0)
            }
            end
        )
    end

    @doc """
    Walk from start to finish, which must be on a horizontal or vertical line from start.
    Returns the steps taken
    """
    def walk(start, finish) do
        sign =  if start.x == finish.x do
                if start.y < finish.y, do: 1, else: -1
            else
                if start.x < finish.x, do: 1, else: -1
            end

        if (start.x == finish.x) do
            Stream.iterate(1, &(&1+1))
                    |> Enum.take(abs(finish.y - start.y))
                    |> Enum.map(fn(y) -> %Vec{x: start.x, y: start.y + y * sign} end)
            else
                Stream.iterate(1, &(&1+1))
                    |> Enum.take(abs(finish.x - start.x))
                    |> Enum.map(fn(x) -> %Vec{x: start.x + x * sign, y: start.y} end)
        end
    end

    @doc """
        Find the first position at which the path given crosses itself
    """
    def findFirstCrossing(input) do
        parseMoveList(input)
        |> Enum.reduce_while(
            %{
                visited: MapSet.new([@origin]),
                position: @origin,
                direction: @n
            },
            fn (item, acc) ->

                # Which direction will we be facing after modifying our current direction with the move's direction?
                newDirection = turnVector(acc[:direction], item[:turnDirection])

                # After moving in newDirection by the move's number of steps, where are we?
                newPosition = %Vec{
                    x: acc[:position].x + newDirection.x * item[:distance],
                    y: acc[:position].y + newDirection.y * item[:distance]
                }

                # What is the path from where we were to where we are now?
                w = walk(acc[:position], newPosition)

                # Debug...
                # IO.puts "#{inspect item} -> #{inspect newDirection} Walking #{inspect w}"

                # Find where we cross a visited node (if at all).
                crossing = Enum.find(w, nil, fn(x) -> MapSet.member?(acc[:visited], x) end)

                case crossing do
                    nil -> {
                        # No crossing found, so let's say we should continue
                        :cont,
                        %{
                            # Add the steps we've walked to the set of visited nodes
                            visited: MapSet.union(acc[:visited], MapSet.new(w)),
                            position: newPosition,
                            direction: newDirection
                        }
                    }
                    # Ah, we found a crossing - stop!
                    _ -> { :halt, crossing }
                end

            end
        )
    end
end

realInput = "R3, L2, L2, R4, L1, R2, R3, R4, L2, R4, L2, L5, L1, R5, R2, R2, L1, R4, R1, L5, L3, R4, R3, R1, L1, L5, L4, L2, R5, L3, L4, R3, R1, L3, R1, L3, R3, L4, R2, R5, L190, R2, L3, R47, R4, L3, R78, L1, R3, R190, R4, L3, R4, R2, R5, R3, R4, R3, L1, L4, R3, L4, R1, L4, L5, R3, L3, L4, R1, R2, L4, L3, R3, R3, L2, L5, R1, L4, L1, R5, L5, R1, R5, L4, R2, L2, R1, L5, L4, R4, R4, R3, R2, R3, L1, R4, R5, L2, L5, L4, L1, R4, L4, R4, L4, R1, R5, L1, R1, L5, R5, R1, R1, L3, L1, R4, L1, L4, L4, L3, R1, R4, R1, R1, R2, L5, L2, R4, L1, R3, L5, L2, R5, L4, R5, L5, R3, R4, L3, L3, L2, R2, L5, L5, R3, R4, R3, R4, R3, R1"

firstCrossing = App.findFirstCrossing(realInput)

IO.puts(firstCrossing.x + firstCrossing.y)

error: pathspec '1.exs' did not match any file(s) known to git


fix: improve declaration requests terminator (#4947)


[patch] fix party info migration (#1942)


add fraud related legal_entities migration (#3335)

fatal: unable to access 'https://github.com/edenlabllc/ehealth.api.git/': The requested URL returned error: 403


Fix credo complains

Fix credo complains


Upgraded httpoison

Upgraded httpoison

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/koenighotze/elixir-lang-exercises.git/'


Document shortcomings of --no-ecto and --no-html flags, closes #2145

defmodule Mix.Tasks.Phx.New do
  @moduledoc """
  Creates a new Phoenix project.

  It expects the path of the project as an argument.

      mix phx.new PATH [--module MODULE] [--app APP]

  A project at the given PATH will be created. The
  application name and module name will be retrieved
  from the path, unless `--module` or `--app` is given.

  ## Options

    * `--umbrella` - generate an umbrella application,
      with one application for your domain, and
      a second application for the web interface.

    * `--app` - the name of the OTP application

    * `--module` - the name of the base module in
      the generated skeleton

    * `--database` - specify the database adapter for ecto.
      Values can be `postgres` or `mysql`. Defaults to `postgres`

    * `--no-brunch` - do not generate brunch files
      for static asset building. When choosing this
      option, you will need to manually handle
      JavaScript dependencies if building HTML apps

    * `--no-ecto` - do not generate Ecto files.

    * `--no-html` - do not generate HTML views.

    * `--binary-id` - use `binary_id` as primary key type
      in Ecto schemas

  When passing the `--no-ecto` flag, Phoenix generators such as
  `phx.gen.html`, `phx.gen.json` and `phx.gen.context` may no
  longer work as expected as they generate context files that rely
  on Ecto for the database access. In those cases, you can pass the
  `--no-context` flag to generate most of the HTML and JSON files
  but skip the context, allowing you to fill in the blanks as desired.

  Similarly, if `--no-html` is given, the files generated by
  `phx.gen.html` will no longer work, as important HTML components
  will be missing.

  ## Examples

      mix phx.new hello_world

  Is equivalent to:

      mix phx.new hello_world --module HelloWorld

  Or without the html bits (useful for APIs):

      mix phx.new ~/Workspace/hello_world --no-html

  As an umbrella:

      mix phx.new hello --umbrella

  Would generate the following directory structure and modules:

      hello_umbrella/   Hello.Umbrella
        apps/
          hello/        Hello
          hello_web/    Hello.Web

  You can read more about umbrella projects using the
  official [Elixir guide](http://elixir-lang.org/getting-started/mix-otp/dependencies-and-umbrella-apps.html#umbrella-projects)
  """
  use Mix.Task
  alias Phx.New.{Generator, Project, Single, Umbrella}

  @version Mix.Project.config[:version]
  @shortdoc "Creates a new Phoenix v#{@version} application using the experimental generators"

  @switches [dev: :boolean, brunch: :boolean, ecto: :boolean,
             app: :string, module: :string, web_module: :string,
             database: :string, binary_id: :boolean, html: :boolean,
             umbrella: :boolean]

  def run([version]) when version in ~w(-v --version) do
    Mix.shell.info "Phoenix v#{@version}"
  end
  def run(argv) do
    elixir_version_check!()
    case parse_opts(argv) do
      {_opts, []}             -> Mix.Tasks.Help.run(["phx.new"])
      {opts, [base_path | _]} ->
        generator = if opts[:umbrella], do: Umbrella, else: Single
        generate(base_path, generator, opts)
    end
  end
  def run(argv, generator) do
    elixir_version_check!()
    case parse_opts(argv) do
      {_opts, []}             -> Mix.Tasks.Help.run(["phx.new"])
      {opts, [base_path | _]} -> generate(base_path, generator, opts)
    end
  end

  def generate(base_path, generator, opts) do
    base_path
    |> Project.new(opts)
    |> generator.prepare_project()
    |> Generator.put_binding()
    |> validate_project()
    |> generator.generate()
    |> prompt_to_install_deps()
  end

  defp validate_project(%Project{opts: opts} = project) do
    check_app_name!(project.app, !!opts[:app])
    check_directory_existence!(project.project_path)
    check_module_name_validity!(project.root_mod)
    check_module_name_availability!(project.root_mod)

    project
  end

  defp prompt_to_install_deps(%Project{} = project) do
    install? = Mix.shell.yes?("\nFetch and install dependencies?")
    starting_dir = File.cwd!()

    maybe_cd(project.project_path, fn ->
      mix? = install_mix(install?)

      maybe_cd(project.web_path, fn ->
        {extra, compile} =
          if mix? do
            {[], Task.async(fn -> cmd("mix deps.compile") end)}
          else
            {["$ mix deps.get"], Task.async(fn -> :ok end)}
          end

        brunch? = install_brunch(install?)
        Task.await(compile, :infinity)

        print_mix_info(project.project_path, extra)
        if Project.ecto?(project), do: print_ecto_info(project)
        if not brunch?, do: print_brunch_info(project, starting_dir)
      end)
    end)
  end
  defp maybe_cd(path, func), do: path && File.cd!(path, func)

  defp parse_opts(argv) do
    case OptionParser.parse(argv, strict: @switches) do
      {opts, argv, []} ->
        {opts, argv}
      {_opts, _argv, [switch | _]} ->
        Mix.raise "Invalid option: " <> switch_to_string(switch)
    end
  end
  defp switch_to_string({name, nil}), do: name
  defp switch_to_string({name, val}), do: name <> "=" <> val

  defp install_brunch(install?) do
    maybe_cmd "cd assets && npm install && node node_modules/brunch/bin/brunch build",
              File.exists?("assets/brunch-config.js"), install? && System.find_executable("npm")
  end

  defp install_mix(install?) do
    maybe_cmd "mix deps.get", true, install? && Code.ensure_loaded?(Hex)
  end

  defp print_brunch_info(%Project{} = project, starting_dir) do
    rel_path =
      project.web_path
      |> Path.relative_to(starting_dir)
      |> Path.relative_to(project.project_path)

    Mix.shell.info """

    Phoenix uses an optional assets build tool called brunch.io
    that requires node.js and npm. Installation instructions for
    node.js, which includes npm, can be found at http://nodejs.org.

    After npm is installed, install your brunch dependencies by
    running the following command inside ./#{rel_path}:

        $ cd assets && npm install

    If you don't want brunch.io, you can re-run this generator
    with the --no-brunch option.
    """
    nil
  end

  defp print_ecto_info(%Project{app_path: nil}), do: nil
  defp print_ecto_info(%Project{app_path: app_path} = project) do
    config_path =
      app_path
      |> Path.join("config/dev.exs")
      |> Path.relative_to(project.project_path)

    Mix.shell.info """
    Before moving on, configure your database in #{config_path} and run:

        $ mix ecto.create
    """
  end

  defp print_mix_info(path, extra) do
    steps = ["$ cd #{relative_app_path(path)}"] ++ extra ++ ["$ mix phx.server"]

    Mix.shell.info """

    We are all set! Run your Phoenix application:

        #{Enum.join(steps, "\n    ")}

    You can also run your app inside IEx (Interactive Elixir) as:

        $ iex -S mix phx.server
    """
  end
  defp relative_app_path(path) do
    case Path.relative_to_cwd(path) do
      ^path -> Path.basename(path)
      rel   -> rel
    end
  end

  ## Helpers

  defp maybe_cmd(cmd, should_run?, can_run?) do
    cond do
      should_run? && can_run? ->
        cmd(cmd)
        true
      should_run? ->
        false
      true ->
        true
    end
  end

  defp cmd(cmd) do
    Mix.shell.info [:green, "* running ", :reset, cmd]
    case Mix.shell.cmd(cmd, quiet: true) do
      0 ->
        true
      _ ->
        Mix.shell.error [:red, "* error ", :reset, "command failed to execute, " <>
          "please run the following command again after installation:\n\n    #{cmd}"]
        false
    end
  end

  defp check_app_name!(name, from_app_flag) do
    unless name =~ ~r/^[a-z][\w_]*$/ do
      extra =
        if !from_app_flag do
          ". The application name is inferred from the path, if you'd like to " <>
          "explicitly name the application then use the `--app APP` option."
        else
          ""
        end

      Mix.raise "Application name must start with a letter and have only lowercase " <>
                "letters, numbers and underscore, got: #{inspect name}" <> extra
    end
  end

  defp check_module_name_validity!(name) do
    unless inspect(name) =~ ~r/^[A-Z]\w*(\.[A-Z]\w*)*$/ do
      Mix.raise "Module name must be a valid Elixir alias (for example: Foo.Bar), got: #{inspect name}"
    end
  end

  defp check_module_name_availability!(name) do
    [name]
    |> Module.concat()
    |> Module.split()
    |> Enum.reduce([], fn name, acc ->
        mod = Module.concat([Elixir, name | acc])
        if Code.ensure_loaded?(mod) do
          Mix.raise "Module name #{inspect mod} is already taken, please choose another name"
        else
          [name | acc]
        end
    end)
  end

  defp check_directory_existence!(path) do
    if File.dir?(path) and not Mix.shell.yes?("The directory #{path} already exists. Are you sure you want to continue?") do
      Mix.raise "Please select another directory for installation."
    end
  end

  defp elixir_version_check! do
    unless Version.match?(System.version, "~> 1.4") do
      Mix.raise "Phoenix v#{@version} requires at least Elixir v1.4.\n " <>
                "You have #{System.version()}. Please update accordingly"
    end
  end
end

defmodule Mix.Tasks.Phx.New do
  @moduledoc """
  Creates a new Phoenix project.

  It expects the path of the project as an argument.

      mix phx.new PATH [--module MODULE] [--app APP]

  A project at the given PATH will be created. The
  application name and module name will be retrieved
  from the path, unless `--module` or `--app` is given.

  ## Options

    * `--umbrella` - generate an umbrella application,
      with one application for your domain, and
      a second application for the web interface.

    * `--app` - the name of the OTP application

    * `--module` - the name of the base module in
      the generated skeleton

    * `--database` - specify the database adapter for ecto.
      Values can be `postgres` or `mysql`. Defaults to `postgres`

    * `--no-brunch` - do not generate brunch files
      for static asset building. When choosing this
      option, you will need to manually handle
      JavaScript dependencies if building HTML apps

    * `--no-ecto` - do not generate ecto files.

    * `--no-html` - do not generate HTML views.

    * `--binary-id` - use `binary_id` as primary key type
      in Ecto schemas

  ## Examples

      mix phx.new hello_world

  Is equivalent to:

      mix phx.new hello_world --module HelloWorld

  Without brunch:

      mix phx.new ~/Workspace/hello_world --no-brunch

  As an umbrella:

      mix phx.new hello --umbrella

  Would generate the following directory structure and modules:

      hello_umbrella/   Hello.Umbrella
        apps/
          hello/        Hello
          hello_web/    Hello.Web

  You can read more about umbrella projects using the
  official [Elixir guide](http://elixir-lang.org/getting-started/mix-otp/dependencies-and-umbrella-apps.html#umbrella-projects)
  """
  use Mix.Task
  alias Phx.New.{Generator, Project, Single, Umbrella}

  @version Mix.Project.config[:version]
  @shortdoc "Creates a new Phoenix v#{@version} application using the experimental generators"

  @switches [dev: :boolean, brunch: :boolean, ecto: :boolean,
             app: :string, module: :string, web_module: :string,
             database: :string, binary_id: :boolean, html: :boolean,
             umbrella: :boolean]

  def run([version]) when version in ~w(-v --version) do
    Mix.shell.info "Phoenix v#{@version}"
  end
  def run(argv) do
    elixir_version_check!()
    case parse_opts(argv) do
      {_opts, []}             -> Mix.Tasks.Help.run(["phx.new"])
      {opts, [base_path | _]} ->
        generator = if opts[:umbrella], do: Umbrella, else: Single
        generate(base_path, generator, opts)
    end
  end
  def run(argv, generator) do
    elixir_version_check!()
    case parse_opts(argv) do
      {_opts, []}             -> Mix.Tasks.Help.run(["phx.new"])
      {opts, [base_path | _]} -> generate(base_path, generator, opts)
    end
  end

  def generate(base_path, generator, opts) do
    base_path
    |> Project.new(opts)
    |> generator.prepare_project()
    |> Generator.put_binding()
    |> validate_project()
    |> generator.generate()
    |> prompt_to_install_deps()
  end

  defp validate_project(%Project{opts: opts} = project) do
    check_app_name!(project.app, !!opts[:app])
    check_directory_existence!(project.project_path)
    check_module_name_validity!(project.root_mod)
    check_module_name_availability!(project.root_mod)

    project
  end

  defp prompt_to_install_deps(%Project{} = project) do
    install? = Mix.shell.yes?("\nFetch and install dependencies?")
    starting_dir = File.cwd!()

    maybe_cd(project.project_path, fn ->
      mix? = install_mix(install?)

      maybe_cd(project.web_path, fn ->
        {extra, compile} =
          if mix? do
            {[], Task.async(fn -> cmd("mix deps.compile") end)}
          else
            {["$ mix deps.get"], Task.async(fn -> :ok end)}
          end

        brunch? = install_brunch(install?)
        Task.await(compile, :infinity)

        print_mix_info(project.project_path, extra)
        if Project.ecto?(project), do: print_ecto_info(project)
        if not brunch?, do: print_brunch_info(project, starting_dir)
      end)
    end)
  end
  defp maybe_cd(path, func), do: path && File.cd!(path, func)

  defp parse_opts(argv) do
    case OptionParser.parse(argv, strict: @switches) do
      {opts, argv, []} ->
        {opts, argv}
      {_opts, _argv, [switch | _]} ->
        Mix.raise "Invalid option: " <> switch_to_string(switch)
    end
  end
  defp switch_to_string({name, nil}), do: name
  defp switch_to_string({name, val}), do: name <> "=" <> val

  defp install_brunch(install?) do
    maybe_cmd "cd assets && npm install && node node_modules/brunch/bin/brunch build",
              File.exists?("assets/brunch-config.js"), install? && System.find_executable("npm")
  end

  defp install_mix(install?) do
    maybe_cmd "mix deps.get", true, install? && Code.ensure_loaded?(Hex)
  end

  defp print_brunch_info(%Project{} = project, starting_dir) do
    rel_path =
      project.web_path
      |> Path.relative_to(starting_dir)
      |> Path.relative_to(project.project_path)

    Mix.shell.info """

    Phoenix uses an optional assets build tool called brunch.io
    that requires node.js and npm. Installation instructions for
    node.js, which includes npm, can be found at http://nodejs.org.

    After npm is installed, install your brunch dependencies by
    running the following command inside ./#{rel_path}:

        $ cd assets && npm install

    If you don't want brunch.io, you can re-run this generator
    with the --no-brunch option.
    """
    nil
  end

  defp print_ecto_info(%Project{app_path: nil}), do: nil
  defp print_ecto_info(%Project{app_path: app_path} = project) do
    config_path =
      app_path
      |> Path.join("config/dev.exs")
      |> Path.relative_to(project.project_path)

    Mix.shell.info """
    Before moving on, configure your database in #{config_path} and run:

        $ mix ecto.create
    """
  end

  defp print_mix_info(path, extra) do
    steps = ["$ cd #{relative_app_path(path)}"] ++ extra ++ ["$ mix phx.server"]

    Mix.shell.info """

    We are all set! Run your Phoenix application:

        #{Enum.join(steps, "\n    ")}

    You can also run your app inside IEx (Interactive Elixir) as:

        $ iex -S mix phx.server
    """
  end
  defp relative_app_path(path) do
    case Path.relative_to_cwd(path) do
      ^path -> Path.basename(path)
      rel   -> rel
    end
  end

  ## Helpers

  defp maybe_cmd(cmd, should_run?, can_run?) do
    cond do
      should_run? && can_run? ->
        cmd(cmd)
        true
      should_run? ->
        false
      true ->
        true
    end
  end

  defp cmd(cmd) do
    Mix.shell.info [:green, "* running ", :reset, cmd]
    case Mix.shell.cmd(cmd, quiet: true) do
      0 ->
        true
      _ ->
        Mix.shell.error [:red, "* error ", :reset, "command failed to execute, " <>
          "please run the following command again after installation:\n\n    #{cmd}"]
        false
    end
  end

  defp check_app_name!(name, from_app_flag) do
    unless name =~ ~r/^[a-z][\w_]*$/ do
      extra =
        if !from_app_flag do
          ". The application name is inferred from the path, if you'd like to " <>
          "explicitly name the application then use the `--app APP` option."
        else
          ""
        end

      Mix.raise "Application name must start with a letter and have only lowercase " <>
                "letters, numbers and underscore, got: #{inspect name}" <> extra
    end
  end

  defp check_module_name_validity!(name) do
    unless inspect(name) =~ ~r/^[A-Z]\w*(\.[A-Z]\w*)*$/ do
      Mix.raise "Module name must be a valid Elixir alias (for example: Foo.Bar), got: #{inspect name}"
    end
  end

  defp check_module_name_availability!(name) do
    [name]
    |> Module.concat()
    |> Module.split()
    |> Enum.reduce([], fn name, acc ->
        mod = Module.concat([Elixir, name | acc])
        if Code.ensure_loaded?(mod) do
          Mix.raise "Module name #{inspect mod} is already taken, please choose another name"
        else
          [name | acc]
        end
    end)
  end

  defp check_directory_existence!(path) do
    if File.dir?(path) and not Mix.shell.yes?("The directory #{path} already exists. Are you sure you want to continue?") do
      Mix.raise "Please select another directory for installation."
    end
  end

  defp elixir_version_check! do
    unless Version.match?(System.version, "~> 1.4") do
      Mix.raise "Phoenix v#{@version} requires at least Elixir v1.4.\n " <>
                "You have #{System.version()}. Please update accordingly"
    end
  end
end


Use clearer language when recommending bang functions in seeds (#1861)

# Script for populating the database. You can run it as:
#
#     mix run priv/repo/seeds.exs
#
# Inside the script, you can read and write to any of your
# repositories directly:
#
#     <%= application_module %>.Repo.insert!(%<%= application_module %>.SomeModel{})
#
# We recommend using the bang functions (`insert!`, `update!`
# and so on) as they will halt execution if something goes wrong.

# Script for populating the database. You can run it as:
#
#     mix run priv/repo/seeds.exs
#
# Inside the script, you can read and write to any of your
# repositories directly:
#
#     <%= application_module %>.Repo.insert!(%<%= application_module %>.SomeModel{})
#
# We recommend using the bang functions (`insert!`, `update!`
# and so on) as they will fail if something goes wrong.


Database: alter users.picture column from varchar to text type

  - see https://stackoverflow.com/questions/219569/best-database-field-type-for-a-url

defmodule :"Elixir.RemoteRetro.Repo.Migrations.Alter-users-url-fields-from-varchar-to-text" do
  use Ecto.Migration

  def up do
    alter table(:users) do
      modify :picture, :text
    end
  end

  def down do
    alter table(:users) do
      modify :picture, :string
    end
  end
end

error: pathspec 'priv/repo/migrations/20191107012247_alter-users-url-fields-from-varchar-to-text.exs' did not match any file(s) known to git


check for magic number in jpeg only in the binary beginning

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/evercam/evercam-server.git/'


Added ColognePhonetics module

Added ColognePhonetics module

This module is functional, but unfinished. This module takes a string
and returns the cologne phonetics encoded value of the string in
string format. It requires a string containing only a-z lowercase,
with no spaces or punctuation to function correctly. This will be
fixed in a future commit.

defmodule Vutuv.ColognePhonetics do

  cologne_replacements_with_rules =
  [
    #This is the replacement list with rules included. The order is very imporant for the correct functionality of the algorithm.
    #This is because the match functions generate in the same order as the rules are defined, and match in the same order as well.
    {?p, '3', %{before: ?h}},

    {?c, '4', %{first: true, before: ?a}},
    {?c, '4', %{first: true, before: ?h}},
    {?c, '4', %{first: true, before: ?k}},
    {?c, '4', %{first: true, before: ?l}},
    {?c, '4', %{first: true, before: ?o}},
    {?c, '4', %{first: true, before: ?q}},
    {?c, '4', %{first: true, before: ?r}},
    {?c, '4', %{first: true, before: ?u}},
    {?c, '4', %{first: true, before: ?x}},

    {?c, '8', %{after: ?s}},
    {?c, '8', %{after: ?z}},

    {?c, '8', %{first: true}},

    {?c, '4', %{before: ?a}},
    {?c, '4', %{before: ?h}},
    {?c, '4', %{before: ?k}},
    {?c, '4', %{before: ?o}},
    {?c, '4', %{before: ?q}},
    {?c, '4', %{before: ?u}},
    {?c, '4', %{before: ?x}},

    {?c, '8', %{first: true}},

    {?d, '8', %{before: ?c}},
    {?d, '8', %{before: ?s}},
    {?d, '8', %{before: ?z}},
    {?t, '8', %{before: ?c}},
    {?t, '8', %{before: ?s}},
    {?t, '8', %{before: ?z}},

    {?x, '8', %{after: ?c}},
    {?x, '8', %{after: ?k}},
    {?x, '8', %{after: ?q}}
  ]

  cologne_replacements =
  [
    #This is the list for basic replacements. Order does not matter here.
    {?a, '0'}, {?e, '0'}, {?i, '0'}, {?j, '0'}, {?o, '0'}, {?u, '0'}, {?y, '0'},
    {?h, ''},
    {?b, '1'}, {?p, '1'},
    {?d, '2'}, {?t, '2'},
    {?f, '3'}, {?v, '3'}, {?w, '3'},
    {?g, '4'}, {?k, '4'}, {?q, '4'},
    {?x, '48'},
    {?l, '5'},
    {?m, '6'}, {?n, '6'},
    {?r, '7'},
    {?s, '8'}, {?z, '8'}, {?c, '8'},
  ]

  def to_cologne(string) do #The three steps of the cologne phonetics algorithm, see https://en.wikipedia.org/wiki/Cologne_phonetics for more info.
    encode_string(string) #Converts the string to representative coded numbers in a char list
    |> Enum.dedup #Removes consecutive duplicates
    |> remove_zeroes #Removes all zeroes, ignoring the first character
    |> to_string #Converts char_list to string for return
  end

  defp encode_string(""), do: ""

  defp encode_string(string) do
    [head|tail] = String.to_char_list(string)
    encode_string('', nil, nil, head, tail) #Initiate recursion
  end

  defp encode_string(encoded, prev, char, next, [head|tail]) do
    encoded++encode(prev, char, next) #As long as the char list is not empty, recurse
    |> encode_string(char, next, head, tail)
  end

  defp encode_string(encoded, prev, char, next, []) do
    encoded #If the char list is empty, the operation  is finished, encode the last two letters.
    ++
    encode(prev, char, next)
    ++
    encode(char, next, nil)
  end

  #This function block defines pattern matchable functions for every possible replacement.
  #This allows for ultra fast processing of the replacements.

  for {char, code, rule} <- cologne_replacements_with_rules do #This generates special rule matches
    cond do
      rule[:before] && rule[:after] -> defp encode(unquote(rule.after), unquote(char), unquote(rule.before)), do: unquote(code)
      rule[:first] && rule[:before] -> defp encode(nil, unquote(char), unquote(rule.before)), do: unquote(code)
      rule[:first] -> defp encode(nil, unquote(char), _), do: unquote(code)
      rule[:before] -> defp encode(_, unquote(char), unquote(rule.before)), do: unquote(code)
      rule[:after]-> defp encode(unquote(rule.after), unquote(char), _), do: unquote(code)
    end
  end

  for {char, code} <- cologne_replacements do #This generates simple matches
    defp encode(_, unquote(char), _), do: unquote(code)
  end

  defp encode(_,nil,_), do: '' #If the recursion is just starting, the selected character will be nil, so don't add to the encoded string.

  defp remove_zeroes([head|tail]) do
    [head|Enum.reject(tail, &(&1 == ?0))]
  end
end

error: pathspec 'lib/vutuv/cologne_phonetics.ex' did not match any file(s) known to git


elixirPracticeSamples: helloworld.ex - hello world in Elixir, variables and string concat

fatal: unable to access 'https://github.com/xmementoit/practiseSamples.git/': The requested URL returned error: 403


Changed ffmpeg params to extract clip from nvr with good quality

fatal: unable to access 'https://github.com/evercam/evercam-media.git/': The requested URL returned error: 403


Add firmware.metadata task

Add firmware.metadata task

It's useful to find out the firmware UUID to match against what's
running on device. This adds a task to do it rather than having to type
`fwup -m -i <path to .fw>`.

fatal: unable to access 'https://github.com/nerves-project/nerves.git/': The requested URL returned error: 403


feat(config): change db

feat(config): change db

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/arcingio/arcing.io.git/'


Adds basic GenServer to do periodic work

fatal: unable to access 'https://github.com/substancelab/pullhub.git/': The requested URL returned error: 403


Fix helpers test

Fix helpers test

defmodule Phoenix.Router.HelpersTest do
  use ExUnit.Case, async: true
  use RouterHelper

  alias Phoenix.Router.Helpers

  ## Unit tests

  test "defhelper with :identifiers" do
    route = build(:match, :get, "/foo/:bar", nil, Hello, :world, "hello_world")

    assert extract_defhelper(route, 0) == String.strip """
    def(hello_world_path(conn_or_endpoint, :world, bar)) do
      hello_world_path(conn_or_endpoint, :world, bar, [])
    end
    """

    assert extract_defhelper(route, 1) == String.strip """
    def(hello_world_path(conn_or_endpoint, :world, bar, params)) do
      path(conn_or_endpoint, segments(("" <> "/foo") <> "/" <> URI.encode_www_form(to_param(bar)), params, ["bar"]))
    end
    """
  end

  test "defhelper with *identifiers" do
    route = build(:match, :get, "/foo/*bar", nil, Hello, :world, "hello_world")

    assert extract_defhelper(route, 0) == String.strip """
    def(hello_world_path(conn_or_endpoint, :world, bar)) do
      hello_world_path(conn_or_endpoint, :world, bar, [])
    end
    """

    assert extract_defhelper(route, 1) == String.strip """
    def(hello_world_path(conn_or_endpoint, :world, bar, params)) do
      path(conn_or_endpoint, segments(("" <> "/foo") <> "/" <> Enum.map_join(bar, "/", &URI.encode_www_form/1), params, ["bar"]))
    end
    """
  end

  defp build(kind, verb, path, host, controller, action, helper) do
    Phoenix.Router.Route.build(kind, verb, path, host, controller, action, helper, [], %{}, %{})
  end

  defp extract_defhelper(route, pos) do
    {:__block__, _, block} = Helpers.defhelper(route, Phoenix.Router.Route.exprs(route))
    Enum.fetch!(block, pos) |> Macro.to_string()
  end

  ## Integration tests

  defmodule Router do
    use Phoenix.Router

    get "/posts/top", PostController, :top, as: :top
    get "/posts/:id", PostController, :show
    get "/posts/file/*file", PostController, :file
    get "/posts/skip", PostController, :skip, as: nil

    resources "/users", UserController do
      resources "/comments", CommentController do
        resources "/files", FileController
      end
    end

    resources "/files", FileController

    resources "/account", UserController, as: :account, singleton: true do
      resources "/page", PagesController, as: :page, only: [:show], singleton: true
    end

    scope "/admin", alias: Admin do
      resources "/messages", MessageController
    end

    scope "/admin/new", alias: Admin, as: "admin" do
      resources "/messages", MessageController
    end

    get "/", PageController, :root, as: :page
  end

  # Emulate regular endpoint functions

  def url do
    "https://example.com"
  end

  def static_url do
    "https://static.example.com"
  end

  def path(path) do
    path
  end

  def static_path(path) do
    path
  end

  alias Router.Helpers

  test "defines a __helpers__ function" do
    assert Router.__helpers__ == Router.Helpers
  end

  test "root helper" do
    conn = conn(:get, "/") |> put_private(:phoenix_endpoint, __MODULE__)
    assert Helpers.page_path(conn, :root) == "/"
    assert Helpers.page_path(__MODULE__, :root) == "/"
  end

  test "url helper with query strings" do
    assert Helpers.post_path(__MODULE__, :show, 5, id: 3) == "/posts/5"
    assert Helpers.post_path(__MODULE__, :show, 5, foo: "bar") == "/posts/5?foo=bar"
    assert Helpers.post_path(__MODULE__, :show, 5, foo: :bar) == "/posts/5?foo=bar"
    assert Helpers.post_path(__MODULE__, :show, 5, foo: true) == "/posts/5?foo=true"
    assert Helpers.post_path(__MODULE__, :show, 5, foo: false) == "/posts/5?foo=false"
    assert Helpers.post_path(__MODULE__, :show, 5, foo: nil) == "/posts/5?foo="

    assert Helpers.post_path(__MODULE__, :show, 5, foo: ~w(bar baz)) ==
           "/posts/5?foo[]=bar&foo[]=baz"
    assert Helpers.post_path(__MODULE__, :show, 5, foo: %{id: 5}) ==
           "/posts/5?foo[id]=5"
    assert Helpers.post_path(__MODULE__, :show, 5, foo: %{__struct__: Foo, id: 5}) ==
           "/posts/5?foo=5"
  end

  test "url helper with param protocol" do
    assert Helpers.post_path(__MODULE__, :show, %{__struct__: Foo, id: 5}) == "/posts/5"

    assert_raise ArgumentError, fn ->
      Helpers.post_path(__MODULE__, :show, nil)
    end
  end

  test "top-level named route" do
    assert Helpers.post_path(__MODULE__, :show, 5) == "/posts/5"
    assert Helpers.post_path(__MODULE__, :show, 5, []) == "/posts/5"
    assert Helpers.post_path(__MODULE__, :show, 5, id: 5) == "/posts/5"
    assert Helpers.post_path(__MODULE__, :show, 5, %{"id" => 5}) == "/posts/5"

    assert Helpers.post_path(__MODULE__, :file, ["foo", "bar"]) == "/posts/file/foo/bar"
    assert Helpers.post_path(__MODULE__, :file, ["foo", "bar"], []) == "/posts/file/foo/bar"

    assert Helpers.top_path(__MODULE__, :top) == "/posts/top"
    assert Helpers.top_path(__MODULE__, :top, id: 5) == "/posts/top?id=5"
    assert Helpers.top_path(__MODULE__, :top, %{"id" => 5}) == "/posts/top?id=5"

    assert_raise UndefinedFunctionError, fn ->
      Helpers.post_path(__MODULE__, :skip)
    end
  end

  test "top-level named routes with complex ids" do
    assert Helpers.post_path(__MODULE__, :show, "==d--+") ==
      "/posts/%3D%3Dd--%2B"
    assert Helpers.post_path(__MODULE__, :show, "==d--+", []) ==
      "/posts/%3D%3Dd--%2B"
    assert Helpers.top_path(__MODULE__, :top, id: "==d--+") ==
      "/posts/top?id=%3D%3Dd--%2B"

    assert Helpers.post_path(__MODULE__, :file, ["==d--+", ":O.jpg"]) ==
      "/posts/file/%3D%3Dd--%2B/%3AO.jpg"
    assert Helpers.post_path(__MODULE__, :file, ["==d--+", ":O.jpg"], []) ==
      "/posts/file/%3D%3Dd--%2B/%3AO.jpg"
    assert Helpers.post_path(__MODULE__, :file, ["==d--+", ":O.jpg"], xx: "/=+/") ==
      "/posts/file/%3D%3Dd--%2B/%3AO.jpg?xx=%2F%3D%2B%2F"
  end

  test "resources generates named routes for :index, :edit, :show, :new" do
    assert Helpers.user_path(__MODULE__, :index, []) == "/users"
    assert Helpers.user_path(__MODULE__, :index) == "/users"
    assert Helpers.user_path(__MODULE__, :edit, 123, []) == "/users/123/edit"
    assert Helpers.user_path(__MODULE__, :edit, 123) == "/users/123/edit"
    assert Helpers.user_path(__MODULE__, :show, 123, []) == "/users/123"
    assert Helpers.user_path(__MODULE__, :show, 123) == "/users/123"
    assert Helpers.user_path(__MODULE__, :new, []) == "/users/new"
    assert Helpers.user_path(__MODULE__, :new) == "/users/new"
  end

  test "resources generated named routes with complex ids" do
    assert Helpers.user_path(__MODULE__, :edit, "1a+/31d", []) == "/users/1a%2B%2F31d/edit"
    assert Helpers.user_path(__MODULE__, :edit, "1a+/31d") == "/users/1a%2B%2F31d/edit"
    assert Helpers.user_path(__MODULE__, :show, "1a+/31d", []) == "/users/1a%2B%2F31d"
    assert Helpers.user_path(__MODULE__, :show, "1a+/31d") == "/users/1a%2B%2F31d"

    assert Helpers.message_path(__MODULE__, :update, "8=/=d", []) == "/admin/messages/8%3D%2F%3Dd"
    assert Helpers.message_path(__MODULE__, :update, "8=/=d") == "/admin/messages/8%3D%2F%3Dd"
    assert Helpers.message_path(__MODULE__, :delete, "8=/=d", []) == "/admin/messages/8%3D%2F%3Dd"
    assert Helpers.message_path(__MODULE__, :delete, "8=/=d") == "/admin/messages/8%3D%2F%3Dd"

    assert Helpers.user_path(__MODULE__, :show, "1a+/31d", [dog: "8d="]) == "/users/1a%2B%2F31d?dog=8d%3D"
    assert Helpers.user_path(__MODULE__, :index, [cat: "=8+/&"]) == "/users?cat=%3D8%2B%2F%26"
  end

  test "resources generates named routes for :create, :update, :delete" do
    assert Helpers.message_path(__MODULE__, :create, []) == "/admin/messages"
    assert Helpers.message_path(__MODULE__, :create) == "/admin/messages"

    assert Helpers.message_path(__MODULE__, :update, 1, []) == "/admin/messages/1"
    assert Helpers.message_path(__MODULE__, :update, 1) == "/admin/messages/1"

    assert Helpers.message_path(__MODULE__, :delete, 1, []) == "/admin/messages/1"
    assert Helpers.message_path(__MODULE__, :delete, 1) == "/admin/messages/1"
  end

  test "1-Level nested resources generates nested named routes for :index, :edit, :show, :new" do
    assert Helpers.user_comment_path(__MODULE__, :index, 99, []) == "/users/99/comments"
    assert Helpers.user_comment_path(__MODULE__, :index, 99) == "/users/99/comments"
    assert Helpers.user_comment_path(__MODULE__, :edit, 88, 2, []) == "/users/88/comments/2/edit"
    assert Helpers.user_comment_path(__MODULE__, :edit, 88, 2) == "/users/88/comments/2/edit"
    assert Helpers.user_comment_path(__MODULE__, :show, 123, 2, []) == "/users/123/comments/2"
    assert Helpers.user_comment_path(__MODULE__, :show, 123, 2) == "/users/123/comments/2"
    assert Helpers.user_comment_path(__MODULE__, :new, 88, []) == "/users/88/comments/new"
    assert Helpers.user_comment_path(__MODULE__, :new, 88) == "/users/88/comments/new"
  end

  test "multi-level nested resources generated named routes with complex ids" do
    assert Helpers.user_comment_path(__MODULE__, :index, "f4/d+~=", []) ==
      "/users/f4%2Fd%2B~%3D/comments"
    assert Helpers.user_comment_path(__MODULE__, :index, "f4/d+~=") ==
      "/users/f4%2Fd%2B~%3D/comments"
    assert Helpers.user_comment_path(__MODULE__, :edit, "f4/d+~=", "x-+=/", []) ==
      "/users/f4%2Fd%2B~%3D/comments/x-%2B%3D%2F/edit"
    assert Helpers.user_comment_path(__MODULE__, :edit, "f4/d+~=", "x-+=/") ==
      "/users/f4%2Fd%2B~%3D/comments/x-%2B%3D%2F/edit"
    assert Helpers.user_comment_path(__MODULE__, :show, "f4/d+~=", "x-+=/", []) ==
      "/users/f4%2Fd%2B~%3D/comments/x-%2B%3D%2F"
    assert Helpers.user_comment_path(__MODULE__, :show, "f4/d+~=", "x-+=/") ==
      "/users/f4%2Fd%2B~%3D/comments/x-%2B%3D%2F"
    assert Helpers.user_comment_path(__MODULE__, :new, "/==/", []) ==
      "/users/%2F%3D%3D%2F/comments/new"
    assert Helpers.user_comment_path(__MODULE__, :new, "/==/") ==
      "/users/%2F%3D%3D%2F/comments/new"

    assert Helpers.user_comment_file_path(__MODULE__, :show, "f4/d+~=", "/==/", "x-+=/", []) ==
      "/users/f4%2Fd%2B~%3D/comments/%2F%3D%3D%2F/files/x-%2B%3D%2F"
    assert Helpers.user_comment_file_path(__MODULE__, :show, "f4/d+~=", "/==/", "x-+=/") ==
      "/users/f4%2Fd%2B~%3D/comments/%2F%3D%3D%2F/files/x-%2B%3D%2F"
  end

  test "2-Level nested resources generates nested named routes for :index, :edit, :show, :new" do
    assert Helpers.user_comment_file_path(__MODULE__, :index, 99, 1, []) ==
      "/users/99/comments/1/files"
    assert Helpers.user_comment_file_path(__MODULE__, :index, 99, 1) ==
      "/users/99/comments/1/files"

    assert Helpers.user_comment_file_path(__MODULE__, :edit, 88, 1, 2, []) ==
      "/users/88/comments/1/files/2/edit"
    assert Helpers.user_comment_file_path(__MODULE__, :edit, 88, 1, 2) ==
      "/users/88/comments/1/files/2/edit"

    assert Helpers.user_comment_file_path(__MODULE__, :show, 123, 1, 2, []) ==
      "/users/123/comments/1/files/2"
    assert Helpers.user_comment_file_path(__MODULE__, :show, 123, 1, 2) ==
      "/users/123/comments/1/files/2"

    assert Helpers.user_comment_file_path(__MODULE__, :new, 88, 1, []) ==
      "/users/88/comments/1/files/new"
    assert Helpers.user_comment_file_path(__MODULE__, :new, 88, 1) ==
      "/users/88/comments/1/files/new"
  end

  test "resources without block generates named routes for :index, :edit, :show, :new" do
    assert Helpers.file_path(__MODULE__, :index, []) == "/files"
    assert Helpers.file_path(__MODULE__, :index) == "/files"
    assert Helpers.file_path(__MODULE__, :edit, 123, []) == "/files/123/edit"
    assert Helpers.file_path(__MODULE__, :edit, 123) == "/files/123/edit"
    assert Helpers.file_path(__MODULE__, :show, 123, []) == "/files/123"
    assert Helpers.file_path(__MODULE__, :show, 123) == "/files/123"
    assert Helpers.file_path(__MODULE__, :new, []) == "/files/new"
    assert Helpers.file_path(__MODULE__, :new) == "/files/new"
  end

  test "resource generates named routes for :show, :edit, :new, :update, :delete" do
    assert Helpers.account_path(__MODULE__, :show, []) == "/account"
    assert Helpers.account_path(__MODULE__, :show) == "/account"
    assert Helpers.account_path(__MODULE__, :edit, []) == "/account/edit"
    assert Helpers.account_path(__MODULE__, :edit) == "/account/edit"
    assert Helpers.account_path(__MODULE__, :new, []) == "/account/new"
    assert Helpers.account_path(__MODULE__, :new) == "/account/new"
    assert Helpers.account_path(__MODULE__, :update, []) == "/account"
    assert Helpers.account_path(__MODULE__, :update) == "/account"
    assert Helpers.account_path(__MODULE__, :delete, []) == "/account"
    assert Helpers.account_path(__MODULE__, :delete) == "/account"
  end

  test "2-Level nested resource generates nested named routes for :show" do
    assert Helpers.account_page_path(__MODULE__, :show, []) == "/account/page"
    assert Helpers.account_page_path(__MODULE__, :show) == "/account/page"
  end

  test "scoped route helpers generated named routes with :path, and :alias options" do
    assert Helpers.message_path(__MODULE__, :index, []) == "/admin/messages"
    assert Helpers.message_path(__MODULE__, :index) == "/admin/messages"
    assert Helpers.message_path(__MODULE__, :show, 1, []) == "/admin/messages/1"
    assert Helpers.message_path(__MODULE__, :show, 1) == "/admin/messages/1"
  end

  test "scoped route helpers generated named routes with :path, :alias, and :helper options" do
    assert Helpers.admin_message_path(__MODULE__, :index, []) == "/admin/new/messages"
    assert Helpers.admin_message_path(__MODULE__, :index) == "/admin/new/messages"
    assert Helpers.admin_message_path(__MODULE__, :show, 1, []) == "/admin/new/messages/1"
    assert Helpers.admin_message_path(__MODULE__, :show, 1) == "/admin/new/messages/1"
  end

  ## Others

  defp conn_with_endpoint do
    conn(:get, "/") |> put_private(:phoenix_endpoint, __MODULE__)
  end

  defp socket_with_endpoint do
    %Phoenix.Socket{endpoint: __MODULE__}
  end

  defp uri do
    %URI{scheme: "https", host: "example.com", port: 443}
  end

  test "helpers module generates a static_path helper" do
    assert Helpers.static_path(__MODULE__, "/images/foo.png") == "/images/foo.png"
    assert Helpers.static_path(conn_with_endpoint, "/images/foo.png") == "/images/foo.png"
    assert Helpers.static_path(socket_with_endpoint, "/images/foo.png") == "/images/foo.png"
  end

  test "helpers module generates a static_url helper" do
    url = "https://static.example.com/images/foo.png"
    assert Helpers.static_url(__MODULE__, "/images/foo.png") == url
    assert Helpers.static_url(conn_with_endpoint, "/images/foo.png") == url
    assert Helpers.static_url(socket_with_endpoint, "/images/foo.png") == url
  end

  test "helpers module generates a url helper" do
    assert Helpers.url(__MODULE__) == "https://example.com"
    assert Helpers.url(conn_with_endpoint) == "https://example.com"
    assert Helpers.url(socket_with_endpoint) == "https://example.com"
    assert Helpers.url(uri) == "https://example.com"
  end

  test "helpers module generates a path helper" do
    assert Helpers.path(__MODULE__, "/") == "/"
    assert Helpers.path(conn_with_endpoint, "/") == "/"
    assert Helpers.path(socket_with_endpoint, "/") == "/"
    assert Helpers.path(uri, "/") == "/"
  end

  test "helpers module generates named routes url helpers" do
    url = "https://example.com/admin/new/messages/1"
    assert Helpers.admin_message_url(__MODULE__, :show, 1) == url
    assert Helpers.admin_message_url(__MODULE__, :show, 1, []) == url
    assert Helpers.admin_message_url(conn_with_endpoint, :show, 1) == url
    assert Helpers.admin_message_url(conn_with_endpoint, :show, 1, []) == url
    assert Helpers.admin_message_url(socket_with_endpoint, :show, 1) == url
    assert Helpers.admin_message_url(socket_with_endpoint, :show, 1, []) == url
    assert Helpers.admin_message_url(uri, :show, 1) == url
    assert Helpers.admin_message_url(uri, :show, 1, []) == url
  end

  ## Script name

  defmodule ScriptName do
    def url do
      "https://example.com"
    end

    def static_url do
      "https://static.example.com"
    end

    def path(path) do
      "/api" <> path
    end

    def static_path(path) do
      "/api" <> path
    end
  end

  def conn_with_script_name(script_name \\ ~w(api)) do
    conn = conn(:get, "/")
           |> put_private(:phoenix_endpoint, ScriptName)
    put_in conn.script_name, script_name
  end

  defp uri_with_script_name do
    %URI{scheme: "https", host: "example.com", port: 123, path: "/api"}
  end

  test "paths use script name" do
    assert Helpers.page_path(ScriptName, :root) == "/api/"
    assert Helpers.page_path(conn_with_script_name(), :root) == "/api/"
    assert Helpers.page_path(uri_with_script_name(), :root) == "/api/"
    assert Helpers.post_path(ScriptName, :show, 5) == "/api/posts/5"
    assert Helpers.post_path(conn_with_script_name(), :show, 5) == "/api/posts/5"
    assert Helpers.post_path(uri_with_script_name(), :show, 5) == "/api/posts/5"
  end

  test "urls use script name" do
    assert Helpers.page_url(ScriptName, :root) ==
           "https://example.com/api/"
    assert Helpers.page_url(conn_with_script_name(), :root) ==
           "https://example.com/api/"
    assert Helpers.page_url(uri_with_script_name(), :root) ==
           "https://example.com:123/api/"

    assert Helpers.post_url(ScriptName, :show, 5) ==
           "https://example.com/api/posts/5"
    assert Helpers.post_url(conn_with_script_name(), :show, 5) ==
           "https://example.com/api/posts/5"
    assert Helpers.post_url(uri_with_script_name(), :show, 5) ==
           "https://example.com:123/api/posts/5"
  end

  test "static does not use script name" do
    assert Helpers.static_path(conn_with_script_name(~w(foo)), "/images/foo.png") ==
           "/api/images/foo.png"

    assert Helpers.static_url(conn_with_script_name(~w(foo)), "/images/foo.png") ==
           "https://static.example.com/api/images/foo.png"
  end
end

defmodule Phoenix.Router.HelpersTest do
  use ExUnit.Case, async: true
  use RouterHelper

  alias Phoenix.Router.Helpers

  ## Unit tests

  test "defhelper with :identifiers" do
    route = build(:match, :get, "/foo/:bar", nil, Hello, :world, "hello_world")

    assert extract_defhelper(route, 0) == String.strip """
    def(hello_world_path(conn_or_endpoint, :world, bar)) do
      hello_world_path(conn_or_endpoint, :world, bar, [])
    end
    """

    assert extract_defhelper(route, 1) == String.strip """
    def(hello_world_path(conn_or_endpoint, :world, bar, params)) do
      path(conn_or_endpoint, segments(("" <> "/foo") <> "/" <> URI.encode_www_form(to_param(bar)), params, ["bar"]))
    end
    """
  end

  test "defhelper with *identifiers" do
    route = build(:match, :get, "/foo/*bar", nil, Hello, :world, "hello_world")

    assert extract_defhelper(route, 0) == String.strip """
    def(hello_world_path(conn_or_endpoint, :world, bar)) do
      hello_world_path(conn_or_endpoint, :world, bar, [])
    end
    """

    assert extract_defhelper(route, 1) == String.strip """
    def(hello_world_path(conn_or_endpoint, :world, bar, params)) do
      path(conn_or_endpoint, segments(("" <> "/foo") <> "/" <> Enum.map_join(bar, "/", &(URI.encode_www_form() / 1)), params, ["bar"]))
    end
    """
  end

  defp build(kind, verb, path, host, controller, action, helper) do
    Phoenix.Router.Route.build(kind, verb, path, host, controller, action, helper, [], %{}, %{})
  end

  defp extract_defhelper(route, pos) do
    {:__block__, _, block} = Helpers.defhelper(route, Phoenix.Router.Route.exprs(route))
    Enum.fetch!(block, pos) |> Macro.to_string()
  end

  ## Integration tests

  defmodule Router do
    use Phoenix.Router

    get "/posts/top", PostController, :top, as: :top
    get "/posts/:id", PostController, :show
    get "/posts/file/*file", PostController, :file
    get "/posts/skip", PostController, :skip, as: nil

    resources "/users", UserController do
      resources "/comments", CommentController do
        resources "/files", FileController
      end
    end

    resources "/files", FileController

    resources "/account", UserController, as: :account, singleton: true do
      resources "/page", PagesController, as: :page, only: [:show], singleton: true
    end

    scope "/admin", alias: Admin do
      resources "/messages", MessageController
    end

    scope "/admin/new", alias: Admin, as: "admin" do
      resources "/messages", MessageController
    end

    get "/", PageController, :root, as: :page
  end

  # Emulate regular endpoint functions

  def url do
    "https://example.com"
  end

  def static_url do
    "https://static.example.com"
  end

  def path(path) do
    path
  end

  def static_path(path) do
    path
  end

  alias Router.Helpers

  test "defines a __helpers__ function" do
    assert Router.__helpers__ == Router.Helpers
  end

  test "root helper" do
    conn = conn(:get, "/") |> put_private(:phoenix_endpoint, __MODULE__)
    assert Helpers.page_path(conn, :root) == "/"
    assert Helpers.page_path(__MODULE__, :root) == "/"
  end

  test "url helper with query strings" do
    assert Helpers.post_path(__MODULE__, :show, 5, id: 3) == "/posts/5"
    assert Helpers.post_path(__MODULE__, :show, 5, foo: "bar") == "/posts/5?foo=bar"
    assert Helpers.post_path(__MODULE__, :show, 5, foo: :bar) == "/posts/5?foo=bar"
    assert Helpers.post_path(__MODULE__, :show, 5, foo: true) == "/posts/5?foo=true"
    assert Helpers.post_path(__MODULE__, :show, 5, foo: false) == "/posts/5?foo=false"
    assert Helpers.post_path(__MODULE__, :show, 5, foo: nil) == "/posts/5?foo="

    assert Helpers.post_path(__MODULE__, :show, 5, foo: ~w(bar baz)) ==
           "/posts/5?foo[]=bar&foo[]=baz"
    assert Helpers.post_path(__MODULE__, :show, 5, foo: %{id: 5}) ==
           "/posts/5?foo[id]=5"
    assert Helpers.post_path(__MODULE__, :show, 5, foo: %{__struct__: Foo, id: 5}) ==
           "/posts/5?foo=5"
  end

  test "url helper with param protocol" do
    assert Helpers.post_path(__MODULE__, :show, %{__struct__: Foo, id: 5}) == "/posts/5"

    assert_raise ArgumentError, fn ->
      Helpers.post_path(__MODULE__, :show, nil)
    end
  end

  test "top-level named route" do
    assert Helpers.post_path(__MODULE__, :show, 5) == "/posts/5"
    assert Helpers.post_path(__MODULE__, :show, 5, []) == "/posts/5"
    assert Helpers.post_path(__MODULE__, :show, 5, id: 5) == "/posts/5"
    assert Helpers.post_path(__MODULE__, :show, 5, %{"id" => 5}) == "/posts/5"

    assert Helpers.post_path(__MODULE__, :file, ["foo", "bar"]) == "/posts/file/foo/bar"
    assert Helpers.post_path(__MODULE__, :file, ["foo", "bar"], []) == "/posts/file/foo/bar"

    assert Helpers.top_path(__MODULE__, :top) == "/posts/top"
    assert Helpers.top_path(__MODULE__, :top, id: 5) == "/posts/top?id=5"
    assert Helpers.top_path(__MODULE__, :top, %{"id" => 5}) == "/posts/top?id=5"

    assert_raise UndefinedFunctionError, fn ->
      Helpers.post_path(__MODULE__, :skip)
    end
  end

  test "top-level named routes with complex ids" do
    assert Helpers.post_path(__MODULE__, :show, "==d--+") ==
      "/posts/%3D%3Dd--%2B"
    assert Helpers.post_path(__MODULE__, :show, "==d--+", []) ==
      "/posts/%3D%3Dd--%2B"
    assert Helpers.top_path(__MODULE__, :top, id: "==d--+") ==
      "/posts/top?id=%3D%3Dd--%2B"

    assert Helpers.post_path(__MODULE__, :file, ["==d--+", ":O.jpg"]) ==
      "/posts/file/%3D%3Dd--%2B/%3AO.jpg"
    assert Helpers.post_path(__MODULE__, :file, ["==d--+", ":O.jpg"], []) ==
      "/posts/file/%3D%3Dd--%2B/%3AO.jpg"
    assert Helpers.post_path(__MODULE__, :file, ["==d--+", ":O.jpg"], xx: "/=+/") ==
      "/posts/file/%3D%3Dd--%2B/%3AO.jpg?xx=%2F%3D%2B%2F"
  end

  test "resources generates named routes for :index, :edit, :show, :new" do
    assert Helpers.user_path(__MODULE__, :index, []) == "/users"
    assert Helpers.user_path(__MODULE__, :index) == "/users"
    assert Helpers.user_path(__MODULE__, :edit, 123, []) == "/users/123/edit"
    assert Helpers.user_path(__MODULE__, :edit, 123) == "/users/123/edit"
    assert Helpers.user_path(__MODULE__, :show, 123, []) == "/users/123"
    assert Helpers.user_path(__MODULE__, :show, 123) == "/users/123"
    assert Helpers.user_path(__MODULE__, :new, []) == "/users/new"
    assert Helpers.user_path(__MODULE__, :new) == "/users/new"
  end

  test "resources generated named routes with complex ids" do
    assert Helpers.user_path(__MODULE__, :edit, "1a+/31d", []) == "/users/1a%2B%2F31d/edit"
    assert Helpers.user_path(__MODULE__, :edit, "1a+/31d") == "/users/1a%2B%2F31d/edit"
    assert Helpers.user_path(__MODULE__, :show, "1a+/31d", []) == "/users/1a%2B%2F31d"
    assert Helpers.user_path(__MODULE__, :show, "1a+/31d") == "/users/1a%2B%2F31d"

    assert Helpers.message_path(__MODULE__, :update, "8=/=d", []) == "/admin/messages/8%3D%2F%3Dd"
    assert Helpers.message_path(__MODULE__, :update, "8=/=d") == "/admin/messages/8%3D%2F%3Dd"
    assert Helpers.message_path(__MODULE__, :delete, "8=/=d", []) == "/admin/messages/8%3D%2F%3Dd"
    assert Helpers.message_path(__MODULE__, :delete, "8=/=d") == "/admin/messages/8%3D%2F%3Dd"

    assert Helpers.user_path(__MODULE__, :show, "1a+/31d", [dog: "8d="]) == "/users/1a%2B%2F31d?dog=8d%3D"
    assert Helpers.user_path(__MODULE__, :index, [cat: "=8+/&"]) == "/users?cat=%3D8%2B%2F%26"
  end

  test "resources generates named routes for :create, :update, :delete" do
    assert Helpers.message_path(__MODULE__, :create, []) == "/admin/messages"
    assert Helpers.message_path(__MODULE__, :create) == "/admin/messages"

    assert Helpers.message_path(__MODULE__, :update, 1, []) == "/admin/messages/1"
    assert Helpers.message_path(__MODULE__, :update, 1) == "/admin/messages/1"

    assert Helpers.message_path(__MODULE__, :delete, 1, []) == "/admin/messages/1"
    assert Helpers.message_path(__MODULE__, :delete, 1) == "/admin/messages/1"
  end

  test "1-Level nested resources generates nested named routes for :index, :edit, :show, :new" do
    assert Helpers.user_comment_path(__MODULE__, :index, 99, []) == "/users/99/comments"
    assert Helpers.user_comment_path(__MODULE__, :index, 99) == "/users/99/comments"
    assert Helpers.user_comment_path(__MODULE__, :edit, 88, 2, []) == "/users/88/comments/2/edit"
    assert Helpers.user_comment_path(__MODULE__, :edit, 88, 2) == "/users/88/comments/2/edit"
    assert Helpers.user_comment_path(__MODULE__, :show, 123, 2, []) == "/users/123/comments/2"
    assert Helpers.user_comment_path(__MODULE__, :show, 123, 2) == "/users/123/comments/2"
    assert Helpers.user_comment_path(__MODULE__, :new, 88, []) == "/users/88/comments/new"
    assert Helpers.user_comment_path(__MODULE__, :new, 88) == "/users/88/comments/new"
  end

  test "multi-level nested resources generated named routes with complex ids" do
    assert Helpers.user_comment_path(__MODULE__, :index, "f4/d+~=", []) ==
      "/users/f4%2Fd%2B~%3D/comments"
    assert Helpers.user_comment_path(__MODULE__, :index, "f4/d+~=") ==
      "/users/f4%2Fd%2B~%3D/comments"
    assert Helpers.user_comment_path(__MODULE__, :edit, "f4/d+~=", "x-+=/", []) ==
      "/users/f4%2Fd%2B~%3D/comments/x-%2B%3D%2F/edit"
    assert Helpers.user_comment_path(__MODULE__, :edit, "f4/d+~=", "x-+=/") ==
      "/users/f4%2Fd%2B~%3D/comments/x-%2B%3D%2F/edit"
    assert Helpers.user_comment_path(__MODULE__, :show, "f4/d+~=", "x-+=/", []) ==
      "/users/f4%2Fd%2B~%3D/comments/x-%2B%3D%2F"
    assert Helpers.user_comment_path(__MODULE__, :show, "f4/d+~=", "x-+=/") ==
      "/users/f4%2Fd%2B~%3D/comments/x-%2B%3D%2F"
    assert Helpers.user_comment_path(__MODULE__, :new, "/==/", []) ==
      "/users/%2F%3D%3D%2F/comments/new"
    assert Helpers.user_comment_path(__MODULE__, :new, "/==/") ==
      "/users/%2F%3D%3D%2F/comments/new"

    assert Helpers.user_comment_file_path(__MODULE__, :show, "f4/d+~=", "/==/", "x-+=/", []) ==
      "/users/f4%2Fd%2B~%3D/comments/%2F%3D%3D%2F/files/x-%2B%3D%2F"
    assert Helpers.user_comment_file_path(__MODULE__, :show, "f4/d+~=", "/==/", "x-+=/") ==
      "/users/f4%2Fd%2B~%3D/comments/%2F%3D%3D%2F/files/x-%2B%3D%2F"
  end

  test "2-Level nested resources generates nested named routes for :index, :edit, :show, :new" do
    assert Helpers.user_comment_file_path(__MODULE__, :index, 99, 1, []) ==
      "/users/99/comments/1/files"
    assert Helpers.user_comment_file_path(__MODULE__, :index, 99, 1) ==
      "/users/99/comments/1/files"

    assert Helpers.user_comment_file_path(__MODULE__, :edit, 88, 1, 2, []) ==
      "/users/88/comments/1/files/2/edit"
    assert Helpers.user_comment_file_path(__MODULE__, :edit, 88, 1, 2) ==
      "/users/88/comments/1/files/2/edit"

    assert Helpers.user_comment_file_path(__MODULE__, :show, 123, 1, 2, []) ==
      "/users/123/comments/1/files/2"
    assert Helpers.user_comment_file_path(__MODULE__, :show, 123, 1, 2) ==
      "/users/123/comments/1/files/2"

    assert Helpers.user_comment_file_path(__MODULE__, :new, 88, 1, []) ==
      "/users/88/comments/1/files/new"
    assert Helpers.user_comment_file_path(__MODULE__, :new, 88, 1) ==
      "/users/88/comments/1/files/new"
  end

  test "resources without block generates named routes for :index, :edit, :show, :new" do
    assert Helpers.file_path(__MODULE__, :index, []) == "/files"
    assert Helpers.file_path(__MODULE__, :index) == "/files"
    assert Helpers.file_path(__MODULE__, :edit, 123, []) == "/files/123/edit"
    assert Helpers.file_path(__MODULE__, :edit, 123) == "/files/123/edit"
    assert Helpers.file_path(__MODULE__, :show, 123, []) == "/files/123"
    assert Helpers.file_path(__MODULE__, :show, 123) == "/files/123"
    assert Helpers.file_path(__MODULE__, :new, []) == "/files/new"
    assert Helpers.file_path(__MODULE__, :new) == "/files/new"
  end

  test "resource generates named routes for :show, :edit, :new, :update, :delete" do
    assert Helpers.account_path(__MODULE__, :show, []) == "/account"
    assert Helpers.account_path(__MODULE__, :show) == "/account"
    assert Helpers.account_path(__MODULE__, :edit, []) == "/account/edit"
    assert Helpers.account_path(__MODULE__, :edit) == "/account/edit"
    assert Helpers.account_path(__MODULE__, :new, []) == "/account/new"
    assert Helpers.account_path(__MODULE__, :new) == "/account/new"
    assert Helpers.account_path(__MODULE__, :update, []) == "/account"
    assert Helpers.account_path(__MODULE__, :update) == "/account"
    assert Helpers.account_path(__MODULE__, :delete, []) == "/account"
    assert Helpers.account_path(__MODULE__, :delete) == "/account"
  end

  test "2-Level nested resource generates nested named routes for :show" do
    assert Helpers.account_page_path(__MODULE__, :show, []) == "/account/page"
    assert Helpers.account_page_path(__MODULE__, :show) == "/account/page"
  end

  test "scoped route helpers generated named routes with :path, and :alias options" do
    assert Helpers.message_path(__MODULE__, :index, []) == "/admin/messages"
    assert Helpers.message_path(__MODULE__, :index) == "/admin/messages"
    assert Helpers.message_path(__MODULE__, :show, 1, []) == "/admin/messages/1"
    assert Helpers.message_path(__MODULE__, :show, 1) == "/admin/messages/1"
  end

  test "scoped route helpers generated named routes with :path, :alias, and :helper options" do
    assert Helpers.admin_message_path(__MODULE__, :index, []) == "/admin/new/messages"
    assert Helpers.admin_message_path(__MODULE__, :index) == "/admin/new/messages"
    assert Helpers.admin_message_path(__MODULE__, :show, 1, []) == "/admin/new/messages/1"
    assert Helpers.admin_message_path(__MODULE__, :show, 1) == "/admin/new/messages/1"
  end

  ## Others

  defp conn_with_endpoint do
    conn(:get, "/") |> put_private(:phoenix_endpoint, __MODULE__)
  end

  defp socket_with_endpoint do
    %Phoenix.Socket{endpoint: __MODULE__}
  end

  defp uri do
    %URI{scheme: "https", host: "example.com", port: 443}
  end

  test "helpers module generates a static_path helper" do
    assert Helpers.static_path(__MODULE__, "/images/foo.png") == "/images/foo.png"
    assert Helpers.static_path(conn_with_endpoint, "/images/foo.png") == "/images/foo.png"
    assert Helpers.static_path(socket_with_endpoint, "/images/foo.png") == "/images/foo.png"
  end

  test "helpers module generates a static_url helper" do
    url = "https://static.example.com/images/foo.png"
    assert Helpers.static_url(__MODULE__, "/images/foo.png") == url
    assert Helpers.static_url(conn_with_endpoint, "/images/foo.png") == url
    assert Helpers.static_url(socket_with_endpoint, "/images/foo.png") == url
  end

  test "helpers module generates a url helper" do
    assert Helpers.url(__MODULE__) == "https://example.com"
    assert Helpers.url(conn_with_endpoint) == "https://example.com"
    assert Helpers.url(socket_with_endpoint) == "https://example.com"
    assert Helpers.url(uri) == "https://example.com"
  end

  test "helpers module generates a path helper" do
    assert Helpers.path(__MODULE__, "/") == "/"
    assert Helpers.path(conn_with_endpoint, "/") == "/"
    assert Helpers.path(socket_with_endpoint, "/") == "/"
    assert Helpers.path(uri, "/") == "/"
  end

  test "helpers module generates named routes url helpers" do
    url = "https://example.com/admin/new/messages/1"
    assert Helpers.admin_message_url(__MODULE__, :show, 1) == url
    assert Helpers.admin_message_url(__MODULE__, :show, 1, []) == url
    assert Helpers.admin_message_url(conn_with_endpoint, :show, 1) == url
    assert Helpers.admin_message_url(conn_with_endpoint, :show, 1, []) == url
    assert Helpers.admin_message_url(socket_with_endpoint, :show, 1) == url
    assert Helpers.admin_message_url(socket_with_endpoint, :show, 1, []) == url
    assert Helpers.admin_message_url(uri, :show, 1) == url
    assert Helpers.admin_message_url(uri, :show, 1, []) == url
  end

  ## Script name

  defmodule ScriptName do
    def url do
      "https://example.com"
    end

    def static_url do
      "https://static.example.com"
    end

    def path(path) do
      "/api" <> path
    end

    def static_path(path) do
      "/api" <> path
    end
  end

  def conn_with_script_name(script_name \\ ~w(api)) do
    conn = conn(:get, "/")
           |> put_private(:phoenix_endpoint, ScriptName)
    put_in conn.script_name, script_name
  end

  defp uri_with_script_name do
    %URI{scheme: "https", host: "example.com", port: 123, path: "/api"}
  end

  test "paths use script name" do
    assert Helpers.page_path(ScriptName, :root) == "/api/"
    assert Helpers.page_path(conn_with_script_name(), :root) == "/api/"
    assert Helpers.page_path(uri_with_script_name(), :root) == "/api/"
    assert Helpers.post_path(ScriptName, :show, 5) == "/api/posts/5"
    assert Helpers.post_path(conn_with_script_name(), :show, 5) == "/api/posts/5"
    assert Helpers.post_path(uri_with_script_name(), :show, 5) == "/api/posts/5"
  end

  test "urls use script name" do
    assert Helpers.page_url(ScriptName, :root) ==
           "https://example.com/api/"
    assert Helpers.page_url(conn_with_script_name(), :root) ==
           "https://example.com/api/"
    assert Helpers.page_url(uri_with_script_name(), :root) ==
           "https://example.com:123/api/"

    assert Helpers.post_url(ScriptName, :show, 5) ==
           "https://example.com/api/posts/5"
    assert Helpers.post_url(conn_with_script_name(), :show, 5) ==
           "https://example.com/api/posts/5"
    assert Helpers.post_url(uri_with_script_name(), :show, 5) ==
           "https://example.com:123/api/posts/5"
  end

  test "static does not use script name" do
    assert Helpers.static_path(conn_with_script_name(~w(foo)), "/images/foo.png") ==
           "/api/images/foo.png"

    assert Helpers.static_url(conn_with_script_name(~w(foo)), "/images/foo.png") ==
           "https://static.example.com/api/images/foo.png"
  end
end


set default value for thumbnailed columns

error: RPC failed; HTTP 403 curl 22 The requested URL returned error: 403
fatal: the remote end hung up unexpectedly


lowering images request for iphone

lowering images request for iphone

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/thluiz/ddd21.git/'


Add Support to Permalinks on Comments

Add Support to Permalinks on Comments

fatal: unable to access 'https://github.com/jaysoifer/jonathansoifer.com.git/': The requested URL returned error: 403


Add call logs to MPI calls

Add call logs to MPI calls

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/edenlabllc/ehealth.api.git/'


Reduce the number of hashing rounds for tests

fatal: unable to access 'https://github.com/akrisanov/playground.git/': The requested URL returned error: 403


photo controller

photo controller

defmodule PedalApp.Web.PhotoControllerTest do
  use PedalApp.Web.ConnCase

  alias PedalApp.Photo

  setup do
    waypoint = insert(:waypoint)
    conn = login(waypoint.tour.user)
    {:ok, conn: conn, waypoint: waypoint}
  end

  defp build_upload(path \\ "test/files/test.jpg") do
    %{__struct__: Plug.Upload, content_type: "image/jpg", path: path, filename: Path.basename(path)}
  end

  test "new", %{conn: conn, waypoint: wp} do
    conn = get conn, "/rider/tours/#{wp.tour.id}/waypoints/#{wp.id}/photos/new"
    assert response(conn, 200)
    assert template(conn) == "new.html"
  end

  test "create", %{conn: conn, waypoint: wp} do
    conn = post conn, "/rider/tours/#{wp.tour.id}/waypoints/#{wp.id}/photos", photo: %{
      file:         build_upload(),
      description:  "Test Description"
    }
    assert Repo.one(Photo)
    assert redirected_to(conn) == "/rider/tours/#{wp.tour.id}/waypoints/#{wp.id}"
  end

  test "create failure", %{conn: conn, waypoint: wp} do
    conn = post conn, "/rider/tours/#{wp.tour.id}/waypoints/#{wp.id}/photos", photo: %{}
    assert response(conn, 200)
    assert template(conn) == "new.html"
  end

  test "edit", %{conn: conn, waypoint: wp} do
    photo = insert(:photo, waypoint: wp)
    conn = get conn, "/rider/tours/#{wp.tour.id}/waypoints/#{wp.id}/photos/#{photo.id}/edit"
    assert response(conn, 200)
    assert template(conn) == "edit.html"
    assert assigns(conn, :photo)
    assert assigns(conn, :changeset)
  end

  test "edit not found", %{conn: conn, waypoint: wp} do
    assert_error_sent 404, fn ->
      get conn, "/rider/tours/#{wp.tour.id}/waypoints/#{wp.id}/photos/0/edit"
    end
  end

  test "update", %{conn: conn, waypoint: wp} do
    photo = insert(:photo, waypoint: wp)
    conn = put conn, "/rider/tours/#{wp.tour.id}/waypoints/#{wp.id}/photos/#{photo.id}", photo: %{
      description: "Updated photo"
    }
    assert redirected_to(conn) == "/rider/tours/#{wp.tour.id}/waypoints/#{wp.id}"
    assert Repo.get_by(Photo, id: photo.id, description: "Updated photo")
  end

  test "update failure", %{conn: conn, waypoint: wp} do
    photo = insert(:photo, waypoint: wp)
    conn = put conn, "/rider/tours/#{wp.tour.id}/waypoints/#{wp.id}/photos/#{photo.id}", photo: %{
      file: ""
    }
    assert response(conn, 200)
    assert template(conn) == "edit.html"
  end

  test "delete", %{conn: conn, waypoint: wp} do
    photo = insert(:photo, waypoint: wp)
    conn = delete conn, "/rider/tours/#{wp.tour.id}/waypoints/#{wp.id}/photos/#{photo.id}"
    assert redirected_to(conn) == "/rider/tours/#{wp.tour.id}/waypoints/#{wp.id}"
    refute Repo.get(Photo, photo.id)
  end
end

error: pathspec 'test/web/controllers/photo_controller_test.exs' did not match any file(s) known to git


Log before deleting

Log before deleting


Increment version [ci skip]

Increment version [ci skip]


refactor for cleared data manipulation

refactor for cleared data manipulation

defmodule Golos.Sync do
  use GenServer
  alias Glasnost.Repo

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

  def init(args) do
    import Ecto.Query
    Repo.delete_all(from c in Glasnost.Post)
    blog_author = RuntimeConfig.blog_author

    state = %{current_cursor: "", blog_author: blog_author, client_mod: RuntimeConfig.blockchain_client_mod}

    Process.send_after(self(), :tick, 1_000)
    {:ok, state}
  end

  def handle_info(:tick, state) do
     utc_now_str = NaiveDateTime.utc_now |> NaiveDateTime.to_iso8601 |> String.replace(~r/\..+/, "")
     {:ok, posts} = state.client_mod.get_discussions_by_author_before_date(state.blog_author, state.current_cursor, utc_now_str, 100)
     posts = posts
      |> Enum.map(fn post -> update_in(post["json_metadata"], &Poison.Parser.parse!(&1)) end )
      |> Enum.map(fn post -> put_in(post, ["tags"], post["json_metadata"]["tags"]) end)
      |> filter_blacklisted(RuntimeConfig.tags(:blacklist))

     for post <- posts do
       save_to_db(post)
     end
     state = iterate(posts, state)
     {:noreply, state}
  end

  def iterate(posts, state) do
    if length(posts) == 100 do
       Process.send_after(self(), :tick, 100, [])
       next_permlink = posts |> List.last() |> Map.get("permlink")
       put_in(state.current_cursor, next_permlink)
     else
       Process.send_after(self(), :tick, :timer.minutes(60), [])
       put_in(state.current_cursor, "")
     end
  end

  def save_to_db(post) do
     result =
       case Repo.get(Glasnost.Post, post["id"]) do
         nil  -> %Glasnost.Post{}
         comment -> comment
       end
       |> Glasnost.Post.changeset(post)
       |> Repo.insert_or_update

     case result do
       {:ok, struct}       -> :ok
       {:error, changeset} -> :error
     end
  end

  def filter_blacklisted(posts, tags) do
    for post <- posts,
      disjoint_tags?(post["tags"], tags),
      do: post
  end

  def disjoint_tags?(tags1, tags2) do
    tags1_set = Enum.into(tags1, MapSet.new)
    tags2_set = Enum.into(tags2, MapSet.new)
    MapSet.disjoint?(tags1_set, tags2_set)
  end

end

defmodule Golos.Sync do
  use GenServer
  alias Glasnost.Repo

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

  def init(args) do
    import Ecto.Query
    Repo.delete_all(from c in Glasnost.Post)
    blog_author = RuntimeConfig.blog_author

    state = %{current_cursor: "", blog_author: blog_author, client_mod: RuntimeConfig.blockchain_client_mod}

    Process.send_after(self(), :tick, 1_000)
    {:ok, state}
  end

  def handle_info(:tick, state) do
     utc_now_str = NaiveDateTime.utc_now |> NaiveDateTime.to_iso8601 |> String.replace(~r/\..+/, "")
     {:ok, posts} = state.client_mod.get_discussions_by_author_before_date(state.blog_author, state.current_cursor, utc_now_str, 100)
     for post <- posts do
      #  IO.inspect post
       post = update_in(post["json_metadata"], &Poison.Parser.parse!(&1))
       post = put_in(post, ["tags"], post["json_metadata"]["tags"])
       save_to_db(post)
     end
     state = iterate(posts, state)
     {:noreply, state}
  end

  def iterate(posts, state) do
    if length(posts) == 100 do
       Process.send_after(self(), :tick, 100, [])
       next_permlink = posts |> List.last() |> Map.get("permlink")
       put_in(state.current_cursor, next_permlink)
     else
       Process.send_after(self(), :tick, :timer.minutes(60), [])
       put_in(state.current_cursor, "")
     end
  end

  def save_to_db(post) do
     result =
       case Repo.get(Glasnost.Post, post["id"]) do
         nil  -> %Glasnost.Post{}
         comment -> comment
       end
       |> Glasnost.Post.changeset(post)
       |> Repo.insert_or_update

     case result do
       {:ok, struct}       -> :ok
       {:error, changeset} -> :error
     end
  end

  def not_in_blacklist?(posts, tags) do
    for post <- posts,
      disjoint_tags?(post["tags"], tags),
      do: post
  end

  def disjoint_tags?(tags1, tags2) do
    tags1_set = Enum.into(tags1, MapSet.new)
    tags2_set = Enum.into(tags2, MapSet.new)
    MapSet.disjoint?(tags1_set, tags2_set)
  end

end


Add PhoenixState to rpunit

Add PhoenixState to rpunit

defmodule RoundingPegs.ExUnit.PhoenixState do
  def start(map), do: Agent.start_link fn -> map end, name: __MODULE__

  def get(key), do: Agent.get(__MODULE__, &Map.get(&1, key))
end

error: pathspec 'lib/rpunit/lib/phoenix_state.ex' did not match any file(s) known to git


Switch to Construction Account only due to 'Error R14 (Memory quota exceeded)'

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/evercam/evercam-admin.git/'


Fixed wrong camera id param

Fixed wrong camera id param


fix typo on view.ex

fix typo on view.ex

fatal: unable to access 'https://github.com/esbullington/addict.git/': The requested URL returned error: 403


Add group_id FK to publishers

Add group_id FK to publishers

Created migration that adds group_id to the publishers table

defmodule JwMinistryApi.Repo.Migrations.AddPublisherGroupId do
  use Ecto.Migration

  def change do
    alter table(:publishers) do
      add :group_id, references(:groups, on_delete: :nothing)
    end

    create index(:publishers, [:group_id])
  end
end

error: pathspec 'priv/repo/migrations/20170617131444_add_publisher_group_id.exs' did not match any file(s) known to git


Problem 002.

Problem 002.

defmodule Main do
  def sumEvens(n1, n2) when n1 + n2 < 4000000 do
    n3 = n1 + n2
    if rem(n3, 2) == 0 do
      n3 + sumEvens(n2, n3)
    else
      sumEvens(n2, n3)
    end
  end

  def sumEvens(_, _) do
    0
  end
end

IO.puts "#{Main.sumEvens(1, 1)}"

error: pathspec '002.ex/main.exs' did not match any file(s) known to git


[minor] fix printout form fixes (#2237)

[minor] fix printout form fixes (#2237)


update kafka brokers

update kafka brokers

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/izakp/APR.git/'


Log database queries

Log database queries

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/evercam/evercam-media.git/'


Allow removing camera details

Allow removing camera details


Change the restart strategy for camera workers to :permanent

We want all workers to be available, even if the camera isn't recording.
Old strategy made sense when we were dynamically stopping unused workers.


Reduced extra code and Used more efficient names.


add name and desc to mix.exs

add name and desc to mix.exs

defmodule WhiteBread.Mixfile do
  use Mix.Project

  def project do
    [app: :white_bread,
     name: "WhiteBread",
     description: """
     Story BDD tool written in and for Elixir.
     Parses Gherkin formatted feature files and executes them as tests.
     """,
     version: "0.1.0",
     elixir: "~> 1.0",
     deps: deps]
  end

  # Configuration for the OTP application
  #
  # Type `mix help compile.app` for more information
  def application do
    [applications: [:logger]]
  end

  # Dependencies can be Hex packages:
  #
  #   {:mydep, "~> 0.3.0"}
  #
  # Or git/path repositories:
  #
  #   {:mydep, git: "https://github.com/elixir-lang/mydep.git", tag: "0.1.0"}
  #
  # Type `mix help deps` for more examples and options
  defp deps do
    []
  end
end

defmodule WhiteBread.Mixfile do
  use Mix.Project

  def project do
    [app: :white_bread,
     version: "0.1.0",
     elixir: "~> 1.0",
     deps: deps]
  end

  # Configuration for the OTP application
  #
  # Type `mix help compile.app` for more information
  def application do
    [applications: [:logger]]
  end

  # Dependencies can be Hex packages:
  #
  #   {:mydep, "~> 0.3.0"}
  #
  # Or git/path repositories:
  #
  #   {:mydep, git: "https://github.com/elixir-lang/mydep.git", tag: "0.1.0"}
  #
  # Type `mix help deps` for more examples and options
  defp deps do
    []
  end
end


Support elixir 0.12

Support elixir 0.12

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/onkel-dirtus/pogo.git/'


Add testcase for AccountIndex

Add testcase for AccountIndex

defmodule Helix.Account.Public.IndexTest do

  use Helix.Test.Case.Integration

  alias Helix.Account.Public.Index, as: AccountIndex

  alias Helix.Test.Server.Setup, as: ServerSetup

  describe "index/1" do
    test "returns the expected data" do
      {server, %{entity: entity}} = ServerSetup.server()

      index = AccountIndex.index(entity)

      assert index.mainframe == server.server_id
    end
  end

  describe "render_index/1" do
    test "returns JSON-friendly index" do
      {_, %{entity: entity}} = ServerSetup.server()

      rendered =
        entity
        |> AccountIndex.index()
        |> AccountIndex.render_index()

      assert is_binary(rendered.mainframe)
    end
  end
end

error: pathspec 'test/account/public/index_test.exs' did not match any file(s) known to git