Bootstrap practice exercises (#774)

Bootstrap practice exercises (#774)

* Bootstrap pratice exercises

* Check if properties can fail, use TODO for types

* Rename exercise_path to exercise_snake_case

* Use Mix.Tasks.Format.run() instead of System.cmd

* Use Macro.underscore

* Mix.install to the top

* Update bin/bootstrap_practice_exercise.exs

Co-authored-by: Angelika Tyborska <f74aefa4323e6a2ebef59e7dc403f763b02378b1@fastmail.com>

# Generate all files required for a practice exercise.
# File content is filled as much as possible, but some, including tests, need manual input.
#
# Run the following command from the root of the repo:
# $ elixir bin/boostrap_practice_exercise.exs complex-numbers
# Pass the name of the exercise (e. g., "complex-numbers") as an argument

Mix.install([
  {:jason, "~> 1.2"},
  {:toml, "~> 0.6"}
])

defmodule Generate do
  def explore_properties(%{"cases" => cases}) when is_list(cases) do
    Enum.map(cases, &Generate.explore_properties/1)
    |> Enum.reduce(
      %{},
      &Map.merge(&1, &2, fn _prop, p1, p2 -> %{p1 | error: p1.error or p2.error} end)
    )
  end

  def explore_properties(%{"property" => property, "input" => input, "expected" => expected}),
    do: %{
      property => %{
        name: Macro.underscore(property),
        variables:
          if match?(%{}, input) do
            Enum.map(input, fn
              {var, %{} = val} -> {var, Enum.map(val, fn {v, _} -> v end)}
              {var, _} -> {var, nil}
            end)
          else
            [{"input", nil}]
          end,
        error: match?(%{"error" => _err}, expected)
      }
    }

  def explore_properties(_data), do: %{}

  def print_property(%{name: name, variables: variables, error: error}) do
    return_type = if error, do: "{:ok, TODO.t()} | {:error, String.t()}", else: "TODO.t()"

    variable_types =
      Enum.map_join(variables, ", ", fn
        {var, nil} ->
          "#{var} :: TODO.t()"

        {var, sub_vars} ->
          "#{var} :: %{#{Enum.map_join(sub_vars, ", ", &(&1 <> " : TODO.t()"))}}"
      end)

    variable_list = Enum.map_join(variables, ", ", fn {var, _} -> var end)

    """
     @doc \"\"\"
     TODO: add function description and replace types in @spec
     \"\"\"
     @spec #{name}(#{variable_types}) :: #{return_type}
     def #{name}(#{variable_list}) do
     end
    """
  end

  def print_comments(comments, do_not_print) do
    comments
    |> Enum.reject(fn {field, _value} -> field in do_not_print end)
    |> Enum.map_join("\n", fn
      {"comments", values} when is_list(values) ->
        "# #{Enum.map_join(values, "\n# ", &String.trim/1)}"

      {field, values} when is_list(values) ->
        "#\n# --#{field} --\n# #{Enum.map_join(values, "\n# ", &inspect/1)}"

      {field, value} ->
        "#\n# -- #{field} --\n# #{inspect(value)}"
    end)
  end

  def print_input(%{} = input),
    do: Enum.map_join(input, "\n", fn {variable, value} -> "#{variable} = #{inspect(value)}" end)

  def print_input(input), do: "input = #{inspect(input)}"

  def print_expected(%{"error" => err}, _error), do: "{:error, #{inspect(err)}}"
  def print_expected(expected, true), do: "{:ok, #{inspect(expected)}}"
  def print_expected(expected, false), do: inspect(expected)

  def print_test_case(
        %{"description" => description, "cases" => sub_cases} = category,
        properties,
        module
      ) do
    """
    describe \"#{description}\" do
    #{Generate.print_comments(category, ["description", "cases"])}
    #{Enum.map_join(sub_cases, "\n\n", &Generate.print_test_case(&1, properties, module))}
    end
    """
  end

  def print_test_case(
        %{
          "description" => description,
          "property" => property,
          "input" => input,
          "expected" => expected
        } = test,
        properties,
        module
      ) do
    %{name: name, variables: variables, error: error} = properties[property]
    variable_list = Enum.map_join(variables, ", ", fn {var, _} -> var end)

    """
    @tag :pending
    test \"#{description}\" do
      #{Generate.print_comments(test, ["description", "property", "input", "expected", "uuid"])}
      #{print_input(input)}
      output = #{module}.#{name}(#{variable_list})
      expected = #{print_expected(expected, error)}

      assert output == expected
    end
    """
  end
end

[exercise] = System.argv()

exercise_snake_case = String.replace(exercise, "-", "_")

module =
  exercise
  |> String.split("-")
  |> Enum.map_join("", &String.capitalize/1)

## Step 1: create folder structure

Mix.Generator.create_directory("exercises/practice/#{exercise}")
Mix.Generator.create_directory("exercises/practice/#{exercise}/.docs")
Mix.Generator.create_directory("exercises/practice/#{exercise}/.meta")
Mix.Generator.create_directory("exercises/practice/#{exercise}/lib")
Mix.Generator.create_directory("exercises/practice/#{exercise}/test")

## Step 2: add common files

# .formatter.exs
format = """
# Used by "mix format"
[
  inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
]
"""

Mix.Generator.create_file("exercises/practice/#{exercise}/.formatter.exs", format)

# mix.exs
mix = """
defmodule #{module}.MixProject do
  use Mix.Project

  def project do
    [
      app: :#{exercise_snake_case},
      version: "0.1.0",
      # elixir: "~> 1.8",
      start_permanent: Mix.env() == :prod,
      deps: deps()
    ]
  end

  # Run "mix help compile.app" to learn about applications.
  def application do
    [
      extra_applications: [:logger]
    ]
  end

  # Run "mix help deps" to learn about dependencies.
  defp deps do
    [
      # {:dep_from_hexpm, "~> 0.3.0"},
      # {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"}
    ]
  end
end
"""

Mix.Generator.create_file("exercises/practice/#{exercise}/mix.exs", mix)

# test/test_helper.exs
test_helper = """
ExUnit.start()
ExUnit.configure(exclude: :pending, trace: true)
"""

Mix.Generator.create_file("exercises/practice/#{exercise}/test/test_helper.exs", test_helper)

## Step 3: write files that depend on problem specifications

url =
  'https://raw.githubusercontent.com/exercism/problem-specifications/main/exercises/#{exercise}'

:inets.start()
:ssl.start()

# .docs/instructions.md
{:ok, {_status, _header, description}} =
  :httpc.request(:get, {url ++ '/description.md', []}, [], [])

Mix.Generator.create_file("exercises/practice/#{exercise}/.docs/instructions.md", description)

# .meta/config.json
{:ok, {_status, _header, metadata}} = :httpc.request(:get, {url ++ '/metadata.toml', []}, [], [])

metadata =
  metadata
  |> to_string
  |> Toml.decode!()

config = %{
  authors: [],
  contributors: [],
  files: %{
    solution: ["lib/#{exercise_snake_case}.ex"],
    test: ["test/#{exercise_snake_case}_test.exs"],
    example: [".meta/example.ex"]
  }
}

config =
  Map.merge(metadata, config)
  |> Jason.encode!(pretty: true)

Mix.Generator.create_file("exercises/practice/#{exercise}/.meta/config.json", config)
IO.puts("Don't forget to add your name and the names of contributors")

# tests and lib files
{:ok, {_status, _header, data}} =
  :httpc.request(:get, {url ++ '/canonical-data.json', []}, [], [])

data = Jason.decode!(data)

properties = Generate.explore_properties(data)

# Generating lib file
lib_file = """
defmodule #{module} do

#{properties |> Map.values() |> Enum.map_join("\n\n", &Generate.print_property/1)}

end
"""

path = "exercises/practice/#{exercise}/lib/#{exercise_snake_case}.ex"
Mix.Generator.create_file(path, lib_file)

Mix.Generator.copy_file(path, "exercises/practice/#{exercise}/.meta/example.ex")

# Generating test file
test_file =
  """
  defmodule #{module}Test do
    use ExUnit.Case

    #{Generate.print_comments(data, ["cases", "exercise"])}
    #{Enum.map_join(data["cases"], "\n\n", &Generate.print_test_case(&1, properties, module))}
  end
  """
  |> String.replace("@tag", "# @tag", global: false)

path = "exercises/practice/#{exercise}/test/#{exercise_snake_case}_test.exs"
Mix.Generator.create_file(path, test_file)

# mix format all files
Mix.Tasks.Format.run(["exercises/practice/#{exercise}/**/*.{ex,exs}"])

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


get id instead party_id

get id instead party_id

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/'


Skip stop streamer if process is nil on CR update.

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/'


[minor] - remove STREET_TYPE from all JSON validation, set SETTLEMENT_TYPE validation just for person (#2157)


Problem 001.

Problem 001.

defmodule Main do
  def sum_less_than(max, increment, current \\ 0) when current < max do
    sum_less_than(max, increment, current + increment) + current
  end

  def sum_less_than(_, _, _) do
    0
  end
end

fives  = Main.sum_less_than(1000, 5)
threes = Main.sum_less_than(1000, 3)
fifteens = Main.sum_less_than(1000, 15)

IO.puts("#{fives + threes - fifteens}")

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


removed extraneous tests from Custom.cmake.ex that are already done in cmake/CompilerOptimizaitons.cmake

# CUSTOM PROPERTIES TO SET

# GLOBAL

#set(CMAKE_BUILD_TYPE "Debug")
set(CMAKE_VERBOSE_MAKEFILE ON)
set(BUILD_STATIC_LIBRARY ON)
set(USE_OPEN_MP OFF)
set(TCL_VERSION 8.5)
set(PYTHON_INCLUDE_DIRS "/usr/include/python2.7")
##set(BUILD_CSOUND_AC OFF)
##set(BUILD_CSOUND_AC_PYTHON_INTERFACE OFF)
##set(BUILD_CSOUND_AC_LUA_INTERFACE OFF)

#### NOTE the processor type needs setting
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -W -Wall -mtune=core2")
## also to test multicore
#set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -W -Wno-missing-field-initializers -Wno-unused-parameter -mtune=core2 -DJPFF")

if(WIN32)
    list(APPEND CMAKE_SYSTEM_INCLUDE_PATH
	    "c:/work/libsndfile-1_0_17")
    list(APPEND CMAKE_SYSTEM_LIBRARY_PATH
	    "c:/work/libsndfile-1_0_17")

    list(APPEND CMAKE_SYSTEM_LIBRARY_PATH
        "c:/Python25/libs")
    list(APPEND CMAKE_SYSTEM_INCLUDE_PATH
        "c:/Python25/include")

endif()

# CUSTOM PROPERTIES TO SET

# GLOBAL

#set(CMAKE_BUILD_TYPE "Debug")
set(CMAKE_VERBOSE_MAKEFILE ON)
set(BUILD_STATIC_LIBRARY ON)
set(USE_OPEN_MP OFF)
set(TCL_VERSION 8.5)
set(PYTHON_INCLUDE_DIRS "/usr/include/python2.7")
##set(BUILD_CSOUND_AC OFF)
##set(BUILD_CSOUND_AC_PYTHON_INTERFACE OFF)
##set(BUILD_CSOUND_AC_LUA_INTERFACE OFF)

#### NOTE the processor type needs setting
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -W -Wall -mtune=core2")
## also to test multicore
#set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -W -Wno-missing-field-initializers -Wno-unused-parameter -mtune=core2 -DJPFF")

include(CheckCCompilerFlag)
check_c_compiler_flag(-ftree-vectorize HAS_TREE_VECTORISE)
if (HAS_TREE_VECTORISE)
    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ftree-vectorize")
endif()

check_c_compiler_flag(-ffast-math HAS_FAST_MATH)
if (HAS_FAST_MATH)
    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ffast-math")
endif()

if(WIN32)
    list(APPEND CMAKE_SYSTEM_INCLUDE_PATH
	    "c:/work/libsndfile-1_0_17")
    list(APPEND CMAKE_SYSTEM_LIBRARY_PATH
	    "c:/work/libsndfile-1_0_17")

    list(APPEND CMAKE_SYSTEM_LIBRARY_PATH
        "c:/Python25/libs")
    list(APPEND CMAKE_SYSTEM_INCLUDE_PATH
        "c:/Python25/include")

endif()


Add new bucket using the bucket.supervisor.

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/julianespinel/tutorials.git/'


Add specs

Add specs

defmodule CLITest do
  use ExUnit.Case

  test "parse_args returns :help when passing --help" do
    import Issues.CLI

    assert run(["--help"]) == :help
  end
end

error: pathspec 'samples/issues/test/cli_test.exs' did not match any file(s) known to git


Add production seed file with hosts and categories

import Jumubase.Factory
alias Jumubase.Repo
alias Jumubase.Accounts.User
alias Jumubase.Foundation.{Category, Host}
alias Jumubase.Showtime.{Participant}

Repo.transaction fn ->
  # Clear existing data
  Repo.delete_all(Host)
  Repo.delete_all(User)
  Repo.delete_all(Category)
  Repo.delete_all(Participant)

  # Create hosts

  insert(:host, name: "DS Bratislava", city: "Bratislava", country_code: "SK", time_zone: "Europe/Bratislava", latitude: 48.1491521, longitude: 17.103554)
  insert(:host, name: "DS Brüssel", city: "Brüssel", country_code: "BE", time_zone: "Europe/Brussels", latitude: 50.8519895, longitude: 4.4926787)
  insert(:host, name: "DS Budapest", city: "Budapest", country_code: "HU", time_zone: "Europe/Budapest", latitude: 47.51, longitude: 18.983813)
  insert(:host, name: "DS Dublin", city: "Dublin", country_code: "IE", time_zone: "Europe/Dublin", latitude: 53.303453, longitude: -6.2293214)
  insert(:host, name: "DS Genf", city: "Genf", country_code: "CH", time_zone: "Europe/Zurich", latitude: 46.2181677, longitude: 6.0874632)
  insert(:host, name: "DS Helsinki", city: "Helsinki", country_code: "FI", time_zone: "Europe/Helsinki", latitude: 60.167165, longitude: 24.93205)
  insert(:host, name: "DS Kopenhagen", city: "Kopenhagen", country_code: "DK", time_zone: "Europe/Copenhagen", latitude: 55.6800835, longitude: 12.5695033)
  insert(:host, name: "DS London", city: "London", country_code: "GB", time_zone: "Europe/London", latitude: 51.4451339, longitude: -0.3050807)
  insert(:host, name: "DS Moskau", city: "Moskau", country_code: "RU", time_zone: "Europe/Moscow", latitude: 55.6643808, longitude: 37.4953562)
  insert(:host, name: "DS Oslo", city: "Oslo", country_code: "NO", time_zone: "Europe/Oslo", latitude: 59.9249933, longitude: 10.7251024)
  insert(:host, name: "DS Paris", city: "Paris", country_code: "FR", time_zone: "Europe/Paris", latitude: 48.8423042, longitude: 2.2035179)
  insert(:host, name: "DS Prag", city: "Prag", country_code: "CZ", time_zone: "Europe/Prague", latitude: 50.0556074, longitude: 14.3541417)
  insert(:host, name: "DS Sofia", city: "Sofia", country_code: "BG", time_zone: "Europe/Sofia", latitude: 42.6691648, longitude: 23.3492821)
  insert(:host, name: "DS Stockholm", city: "Stockholm", country_code: "SE", time_zone: "Europe/Stockholm", latitude: 59.3422421, longitude: 18.0699085)
  insert(:host, name: "DS Warschau", city: "Warschau", country_code: "PL", time_zone: "Europe/Warsaw", latitude: 52.1577924, longitude: 21.0691116)
  insert(:host, name: "DS Doha", city: "Doha", country_code: "QA", time_zone: "Asia/Qatar", latitude: 25.2559086, longitude: 51.501849)

  # Create categories

  insert(:category, name: "\"Kinder musizieren\"", short_name: "Kimu", genre: "kimu", type: "solo_or_ensemble")

  insert(:category, name: "Akkordeon solo", short_name: "Akkordeon", genre: "classical", type: "solo")
  insert(:category, name: "Blockflöte solo", short_name: "Blockflöte", genre: "classical", type: "solo")
  insert(:category, name: "Fagott solo", short_name: "Fagott", genre: "classical", type: "solo")
  insert(:category, name: "Gesang solo", short_name: "Gesang", genre: "classical", type: "solo")
  insert(:category, name: "Gitarre solo", short_name: "Gitarre", genre: "classical", type: "solo")
  insert(:category, name: "Harfe solo", short_name: "Harfe", genre: "classical", type: "solo")
  insert(:category, name: "Horn solo", short_name: "Horn", genre: "classical", type: "solo")
  insert(:category, name: "Kantele solo", short_name: "Kantele", genre: "classical", type: "solo")
  insert(:category, name: "Klarinette solo", short_name: "Klarinette", genre: "classical", type: "solo")
  insert(:category, name: "Klavier solo", short_name: "Klavier", genre: "classical", type: "solo")
  insert(:category, name: "Kontrabass solo", short_name: "Kontrabass", genre: "classical", type: "solo")
  insert(:category, name: "Mallets solo", short_name: "Mallets", genre: "classical", type: "solo")
  insert(:category, name: "Mandoline solo", short_name: "Mandoline", genre: "classical", type: "solo")
  insert(:category, name: "Oboe solo", short_name: "Oboe", genre: "classical", type: "solo")
  insert(:category, name: "Orgel solo", short_name: "Orgel", genre: "classical", type: "solo")
  insert(:category, name: "Percussion solo", short_name: "Percussion", genre: "classical", type: "solo")
  insert(:category, name: "Posaune solo", short_name: "Posaune", genre: "classical", type: "solo")
  insert(:category, name: "Querflöte solo", short_name: "Querflöte", genre: "classical", type: "solo")
  insert(:category, name: "Saxophon solo", short_name: "Saxophon", genre: "classical", type: "solo")
  insert(:category, name: "Tenorhorn/Bariton/Euphonium solo", short_name: "ThBarEuph", genre: "classical", type: "solo")
  insert(:category, name: "Trompete/Flügelhorn solo", short_name: "Trompete", genre: "classical", type: "solo")
  insert(:category, name: "Tuba solo", short_name: "Tuba", genre: "classical", type: "solo")
  insert(:category, name: "Viola solo", short_name: "Viola", genre: "classical", type: "solo")
  insert(:category, name: "Violine solo", short_name: "Violine", genre: "classical", type: "solo")
  insert(:category, name: "Violoncello solo", short_name: "Cello", genre: "classical", type: "solo")
  insert(:category, name: "Zither solo", short_name: "Zither", genre: "classical", type: "solo")

  insert(:category, name: "Akkordeon-Kammermusik", short_name: "AkkKammer", genre: "classical", type: "ensemble")
  insert(:category, name: "Besondere Ensembles: Alte Musik", short_name: "BesEnsAlteMusik", genre: "classical", type: "ensemble")
  insert(:category, name: "Besondere Ensembles: Klassik, Romantik, Spätromantik & Klassische Moderne", short_name: "BesEnsKlassik", genre: "classical", type: "ensemble")
  insert(:category, name: "Bläser-Ensemble", short_name: "BläserEns", genre: "classical", type: "ensemble")
  insert(:category, name: "Duo: Klavier & Blasinstrument", short_name: "Klavier+Bläser", genre: "classical", type: "ensemble")
  insert(:category, name: "Duo: Klavier & Streichinstrument", short_name: "Klavier+Streicher", genre: "classical", type: "ensemble")
  insert(:category, name: "Duo Kunstlied", short_name: "Kunstlied", genre: "classical", type: "ensemble")
  insert(:category, name: "Harfen-Ensemble", short_name: "HarfenEns", genre: "classical", type: "ensemble")
  insert(:category, name: "Klavier-Kammermusik", short_name: "KlavierKammer", genre: "classical", type: "ensemble")
  insert(:category, name: "Klavier vierhändig", short_name: "Klavier4H", genre: "classical", type: "ensemble")
  insert(:category, name: "Neue Musik", short_name: "NeueMusik", genre: "classical", type: "ensemble")
  insert(:category, name: "Schlagzeug-Ensemble", short_name: "SchlagzEns", genre: "classical", type: "ensemble")
  insert(:category, name: "Streicher-Ensemble", short_name: "StreicherEns", genre: "classical", type: "ensemble")
  insert(:category, name: "Vokal-Ensemble", short_name: "VokalEns", genre: "classical", type: "ensemble")
  insert(:category, name: "Zupf-Ensemble", short_name: "ZupfEns", genre: "classical", type: "ensemble")

  insert(:category, name: "Drumset (Pop) solo", short_name: "PopDrums", genre: "popular", type: "solo")
  insert(:category, name: "E-Bass (Pop) solo", short_name: "PopBass", genre: "popular", type: "solo")
  insert(:category, name: "Gesang (Pop) solo", short_name: "PopGesang", genre: "popular", type: "solo")
  insert(:category, name: "Gitarre (Pop) solo", short_name: "PopGitarre", genre: "popular", type: "solo")
  insert(:category, name: "Instrumental-Solo (Pop)", short_name: "PopInstr", genre: "popular", type: "solo")
  insert(:category, name: "Musical", short_name: "Musical", genre: "popular", type: "solo")

  insert(:category, name: "Vokal-Ensemble (Pop)", short_name: "PopVokalEns", genre: "popular", type: "ensemble")
end

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


Show specific mismatches during sign comparison


Board channel monitor genserver

Board channel monitor genserver

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/gtcode/phoenix-trello.git/'


Fixed issue in creating tolen for stream

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/'


Add missing @moduledoc

Add missing @moduledoc

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/futhr/fux.git/'


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/'


Act as a proxy when snapshot range is requested


add prod secret path

add prod secret path


Add handler test

Add handler test

defmodule Phoenix.Socket.HandlerTest do
  use ExUnit.Case, async: true
  import Phoenix.Socket.Handler
  alias Phoenix.Socket

  test "verify correct return from terminate" do
    terminate(%Socket{pid: self})
    assert_received :shutdown
  end

  test "verify correct return from hibernate" do
    hibernate(%Socket{pid: self})
    assert_received :hibernate
  end

  test "verify basic reply" do
    socket = %Socket{pid: self}
    reply(socket, {:text, "hello"})
    assert_received {:reply, {:text, "hello"}, socket}
  end
end

error: pathspec 'test/phoenix/socket/handler_test.exs' did not match any file(s) known to git


Allow user to return public archive

Allow user to return public archive


commented out unused preload methods

commented out unused preload methods

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/udia-software/udia.git/'


use correct legal_entity_id for employee divisions validations (#2786)


played with bitstrings a bit, cool, best pm ever

defmodule Bitstringer do
  # Output is a section of one bute(8 bits)
  # in output they are represented as a decimal number
  def separation do
    <<21421531142142141412::256>>

    <<1::1, 1::1, 1::1, 1::1, 1::1, 1::1, 1::1, 1::1>> == <<255>>
  end
end

error: pathspec 'elixir/bitstrings.ex' did not match any file(s) known to git


load history from uber

load history from uber

defmodule RemoteHistory do
  @limit 20

  def load(query) do
    load_from_uber([], query, 0)
  end

  defp load_from_uber(all, query, offset) do
    query.client
    |> Uber.Api.history(offset, @limit)
    |> Map.fetch!("history")
    |> collect(all, query, offset)
  end

  defp collect([], all, _query, _offset), do: all

  defp collect(rides, all, query, offset) do
    earliest_ride = List.first(rides)

    if earliest_ride["request_time"] < query.from do
      all
    else
      rides
      |> filter_rides(query)
      |> Enum.concat(all)
      |> load_from_uber(query, offset + @limit)
    end
  end

  defp filter_rides(rides, query) do
    rides
    |> Stream.filter(fn r -> on_this_week?(query, r) end)
    |> Stream.map(fn r -> Map.put(r, "rider_id", query.rider_id) end)
    |> Enum.to_list
  end

  defp on_this_week?(query, ride) do
    Enum.member?(query.from..query.to, ride["request_time"])
  end
end

error: pathspec 'web/services/uber/remote_history.ex' did not match any file(s) known to git


Fixed addresses error rendering (#305)

Fixed addresses error rendering (#305)


Added task to import all requestees to zoho


maps operations

maps operations

map = %{ name: "Dave", likes: "Programming", where: "Dallas"}

IO.inspect Map.keys map

IO.inspect Map.values map

IO.inspect map[:name]

IO.inspect map.name

map1 = Map.drop map,[:where, :likes]
IO.inspect map1

map2 = Map.put map, :also_likes, "Ruby"
IO.inspect map2

IO.inspect Map.keys map2

{ value, update_map } = Map.pop map2, :also_likes

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


erlang memory

erlang memory

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


Add test sendrecv in elixir

Add test sendrecv in elixir

defmodule SendRecv do
  @moduledoc """
  MPI Benchmark [SendRecv] in elixir by Filipe Varjão <frgv@cin.ufpe.br>
  """

  def run(data_size_str, rep_str, qtd_procs_str) do

    data_size = binary_to_integer(data_size_str)
    rep =  binary_to_integer(rep_str)
    qtd_procs = binary_to_integer(qtd_procs_str)

    data = generate_data(data_size)

    spawn_start = time_microseg()
    second = create_procs(qtd_procs)
    spawn_end = time_microseg()

    exec_start = time_microseg()
    sender_ring_node(data, rep, second)
    exec_end = time_microseg()

    total_time = exec_end - exec_start
    spawn_time = spawn_end - spawn_start

    # PRINT RESULT
    IO.puts "bytes #{data_size_str} | repetitions #{rep} | exec_time[µsec] #{total_time} | MBytes/sec #{spawn_time} | spawn_time #{bandwidth_calc(data_size, total_time)}"

  end

  def ring_node(right_peer) do
    receive do
      data ->
        right_peer |> send(data)
        ring_node(right_peer)
    end
  end

  def create_procs(qtd_procs) do
    List.foldl(
      :lists.seq(qtd_procs, 2, -1),
      self,
      fn(_id, right_peer) -> spawn(__MODULE__, :ring_node, [right_peer]) end
    )
  end

  def sender_ring_node(_, 0, _) do
    :ok
  end

  def sender_ring_node(data, rep, second) do
    second |> send(data)
    receive do
      data ->
        sender_ring_node(data, rep - 1, second)
    end
  end

  def bandwidth_calc(data, time) do
    megabytes = (data / :math.pow(2, 20))
    seconds = time * 1.0e-6
    megabytes / seconds
  end

  def generate_data(size), do: generate_data(size, [])

  def generate_data(0, bytes), do: iolist_to_binary(bytes)

  def generate_data(size, bytes), do: generate_data(size - 1, [1 | bytes])

  def time_microseg() do
    {ms, s, us} = :erlang.now()
    (ms * 1.0e+12) + (s * 1.0e+6) + us
  end
end

IO.inspect SendRecv.run("5", "100", "2")

error: pathspec 'examples/MPI_Benchmark/source_code/sendrecv/elixir/sendrecv.ex' did not match any file(s) known to git


Use correct variable name

Use correct variable name

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/kidaa/parallel-1.git/'


Finally a decent solution that I can understand. geez ahhhh

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/pdgonzalez872/work_samples.git/'


refactor: Simplify nested case expression

The `primitive` function currently evaluates two nested case
expressions. Simplify this to a single case expression over the tuple of
operator and stack.

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/Bugfry/exercises.git/'


On delete camera added (deleted) in camera name on zoho


Fixed value for status on update_status.


Remove dead comment

Remove dead comment

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/preciz/insta_scrapex.git/'


adds code_change/3 hook to application

adds code_change/3 hook to application

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/lookuppm/package_finder.git/'


Handle add hook

Handle add hook

defmodule Iris.Hook do
  use GenServer

  def start_link do
    GenServer.start_link(__MODULE__, [])
  end

  def init(_) do
    tab = :ets.new(:hooks, [:public, :named_table])
    {:init, %{tab: tab}}
  end

  def handle_call({:add, hook, module, fun, prio}, _from, state) do
    case :ets.lookup(:hooks, hook) do
      [{^hook, callbacks}] ->
        new_hook = sort_by_prio([{module, fun, prio} | callbacks])
        :ets.insert(:hooks, new_hook)
      [] ->
        :ets.insert(:hooks, {hook, [{module, fun, prio}]})
    end
    {:reply, :ok, state}
  end

  defp sort_by_prio(callbacks) do
    Enum.sort(callbacks, &(elem(&1, 2) <= elem(&2, 2)))
  end
end

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


Rewrite applications

Rewrite applications

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/bit-engine/dustbin.git/'


missed adding

missed adding

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/sschneider1207/Geosnap.git/'


First test of observers and plugins

First test of observers and plugins

defmodule Baumeister.ObserverTest do
  use ExUnit.Case

  require Logger

  alias Baumeister.Test.TestListener
  alias Experimental.GenStage

  alias Baumeister.Coordinator
  alias Baumeister.Worker
  alias Baumeister.BaumeisterFile
  alias Baumeister.Observer
  alias Baumeister.Observer.FailPlugin
  alias Baumeister.Observer.NoopPlugin

  def wait_for(pred) do
    case pred.() do
      false ->
        Process.sleep(1)
        wait_for(pred)
      _ -> true
    end
  end

  @tag timeout: 1_000
  test "observe with a failing plugin" do
    # need process flag, because Observer will crash
    Process.flag(:trap_exit, true)
    {:ok, listener} = TestListener.start()
    GenStage.sync_subscribe(listener, to: Baumeister.EventCenter)
    {:ok, pid} = Observer.start_link(FailPlugin, :ok)
    assert is_pid(pid)

    :ok = Observer.run(pid)
    # Process.sleep(10)
    wait_for fn -> length(TestListener.get(listener)) >= 2 end

    l = TestListener.get(listener)
    assert length(l) == 2
    assert [{_, :start_observer, _}, {_, :failed_observer, _}] = l

    # It should really die, otherwise it's not implemented as it should
    Logger.debug "Test Observer"
    refute Process.alive?(pid)
  end

  # GENERAL TODO:
  # * Allow the state of the observer change
  # * Introduce `:stop` as addition to `:ok` and `:error`
  # * Think carefully about nesting of plugins to enable
  #   timings, delays, ... Similar to the Plug-Concept.

end

error: pathspec 'apps/baumeister/test/observer_test.exs' did not match any file(s) known to git


Test basic interactions

Test basic interactions

defmodule XandraTest do
  use ExUnit.Case

  alias Xandra.{SchemaChange, Void}

  defp with_test_keyspace(fun) do
    {:ok, conn} = Xandra.start_link()
    try do
      {:ok, _} = Xandra.execute(conn, "CREATE KEYSPACE xandra_test WITH replication = {'class': 'SimpleStrategy', 'replication_factor': 1}", [], [])
      {:ok, _} = Xandra.execute(conn, "USE xandra_test", [], [])
      fun.(conn)
    after
      Xandra.execute(conn, "DROP KEYSPACE xandra_test", [], [])
    end
  end

  test "basic interactions" do
    with_test_keyspace(fn conn ->
      statement = "CREATE TABLE users (code int, name text, PRIMARY KEY (code, name))"
      {:ok, result} = Xandra.execute(conn, statement, [])
      assert result == %SchemaChange{
        effect: "CREATED",
        options: %{
          keyspace: "xandra_test",
          subject: "users",
        },
        target: "TABLE",
      }

      statement = """
      BEGIN BATCH
      INSERT INTO users (code, name) VALUES (1, 'Marge');
      INSERT INTO users (code, name) VALUES (1, 'Homer');
      INSERT INTO users (code, name) VALUES (1, 'Lisa');
      INSERT INTO users (code, name) VALUES (2, 'Moe');
      INSERT INTO users (code, name) VALUES (3, 'Ned');
      INSERT INTO users (code, name) VALUES (3, 'Burns');
      INSERT INTO users (code, name) VALUES (4, 'Bob');
      APPLY BATCH
      """
      {:ok, result} = Xandra.execute(conn, statement, [])
      assert result == %Void{}

      statement = "SELECT name FROM users WHERE code = :code"
      {:ok, result} = Xandra.execute(conn, statement, %{"code" => {"int", 3}})
      assert Enum.to_list(result) == [
        %{"name" => "Burns"}, %{"name" => "Ned"}
      ]

      statement = "SELECT name FROM users WHERE code = :code"
      {:ok, query} = Xandra.prepare(conn, statement)

      {:ok, result} = Xandra.execute(conn, query, %{"code" => {"int", 1}})
      assert Enum.to_list(result) == [
        %{"name" => "Homer"}, %{"name" => "Lisa"}, %{"name" => "Marge"}
      ]
      {:ok, result} = Xandra.execute(conn, query, %{"code" => {"int", 2}})
      assert Enum.to_list(result) == [
        %{"name" => "Moe"}
      ]
    end)
  end
end

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


Add smoke_test.exs

Add smoke_test.exs

defmodule UpsidedownLeds.SmokeTest do
  defp blink(pid, delay_during \\ 500, delay_after \\ 500) do
    Gpio.write(pid, 1)
    :timer.sleep(delay_during)
    Gpio.write(pid, 0)
    :timer.sleep(delay_after)
  end

  def go do
    pin_defs = %{
      "A" => 4,
      "B" => 2,
      "C" => 27,
      "D" => 22,
      "E" => 26,
      "F" => 19,
      "G" => 13,
      "H" => 6,
      "I" => 5,
      "J" => 11,
      "K" => 9,
      "L" => 10,
      "M" => 3,
      "N" => 14,
      "O" => 15,
      "P" => 8,
      "Q" => 18,
      "R" => 23,
      "S" => 21,
      "T" => 17,
      "U" => 24,
      "V" => 25,
      "W" => 7,
      "X" => 12,
      "Y" => 16,
      "Z" => 20,
    }

    pin_map = pin_defs |> Enum.map(fn pair -> {letter, pin_no} = pair; {:ok, pid} = Gpio.start_link(pin_no, :output); {letter, pid} end) |> Enum.into(%{})

    ?A..?Z |> Enum.each(fn letter -> pid = pin_map[to_string([letter])]; blink(pid, 300, 0); end)

    :timer.sleep(2000)

    "HELLO" |> String.to_charlist |> Enum.each(fn letter -> pid = pin_map[to_string([letter])]; blink(pid); end)
  end
end

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


fix qualify check_innm_id

fix qualify check_innm_id

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/'


funtion without arguments

funtion without arguments

greet = fn -> IO.puts "Hello" end

greet.()

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


Refactor encoder

Refactor encoder

defmodule Jsox.Encoder.Helper do

  import Jsox.Encoder

  use Bitwise

  @escape_map %{
    ?\\ => '\\\\',
    ?\" => '\\"',
    ?\n => '\\n',
    ?\r => '\\r',
    ?\b => '\\b',
    ?\f => '\\f',
    ?\t => '\\t',
    ?\/ => '\\/' }

  def escape(str), do: [?", escape(str, []), ?"]

  defp escape("", chars), do: Enum.reverse(chars)
  for {char, seq} <- Map.to_list(@escape_map) do
    defp escape(<<unquote(char)>> <> data, chars) do
      escape(data, [unquote(seq)|chars])
    end
  end

  defp escape(<<char>> <> data, chars)
    when char <= 0x1F or char == 0x7F,
    do: escape(data, [unicode(char)|chars])

  defp escape(<<char :: utf8>> <> data, chars)
    when char in 0x80..0x9F,
    do: escape(data, [unicode(char)|chars])

  defp escape(<<char :: utf8>> <> data, chars)
    when char in 0xA0..0xFFFF,
    do: surrogate(data, [unicode(char)|chars])

  defp escape(<<char>> <> data, chars),
    do: escape(data, [char|chars])

  defp surrogate(<<char>> <> data, chars) when char > 0xFFFF do
    code = char - 0x10000
    [unicode(0xD800 ||| (code >>> 10)),
     unicode(0xDC00 ||| (code &&& 0x3FF))
     | escape(data, chars)]
  end

  defp surrogate(data, chars),
    do: escape(data, chars)

  defp unicode(char) do
    code = Integer.to_charlist(char, 16)
    case length(code) do
      1 -> ["\\u000", code]
      2 -> ["\\u00", code]
      3 -> ["\\u0", code]
      4 -> ["\\u", code]
    end
  end

  def list([item]), do: [?[, to_json(item, iodata: true) ,?]]

  def list([head|tail]),
    do: [?[, list(tail, [?,, to_json(head, iodata: true)]), ?]]

  defp list([item], acc),
    do: Enum.reverse([to_json(item, iodata: true)|acc])

  defp list([head|tail], acc),
    do: list(tail, [[to_json(head, iodata: true), ?,]|acc])

  def map(map), do: [?{, _map(map), ?}]

  defp _map(map),
    do: map
        |> Map.to_list
        |> Enum.map(&_map_item/1)
        |> Enum.intersperse(?,)

  defp _map_item({key, value}),
    do: [escape(key), ?:, to_json(value, iodata: true)]

end

error: pathspec 'lib/jsox/encoder/helper.ex' did not match any file(s) known to git


Fix error in db handler when the error message is not a map

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/'


Add generated add_fields_to_users migration

defmodule MyApp_726605.Repo.Migrations.AddFieldsToUsers do
  use Ecto.Migration

  def change do
  end
end

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


fix defaultvalue

fix defaultvalue

defmodule HttpProxy.Handle do
  @moduledoc """
  Handle every http request to outside of the server.
  """

  use Plug.Builder
  import Plug.Conn
  require Logger

  alias HttpProxy.Play.Data, as: Data
  alias HttpProxy.Record.Response, as: Record
  alias HttpProxy.Play.Response, as: Play

  @proxies Application.get_env :http_proxy, :proxies
  @scheme Application.get_env(:http_proxy, :schemes) || [:http, :https]

  plug Plug.Logger
  plug :dispatch

  # Same as Plug.Conn https://github.com/elixir-lang/plug/blob/576c04c2cba778f1ac9ca28aa71c50efa1046b50/lib/plug/conn.ex#L125
  @type t :: %Plug.Conn{}

  @type param           :: binary | [param]

  @doc """
  Start Cowboy http process with localhost and arbitrary port.
  Clients access to local Cowboy process with HTTP potocol.
  """
  @spec start_link([binary]) :: pid
  def start_link([proxy, module_name]) do
    Logger.info "Running Proxy with Cowboy on http://localhost:#{proxy.port} named #{module_name}"
    Plug.Adapters.Cowboy.http(__MODULE__, [], [port: proxy.port, ref: String.to_atom(module_name)])
  end

  @doc """
  Dispatch connection and Play/Record http/https requests.
  """
  @spec dispatch(t, param) :: t
  def dispatch(conn, _opts) do
    {:ok, client} = String.downcase(conn.method)
                    |> String.to_atom
                    |> :hackney.request(uri(conn), conn.req_headers, :stream, [])
    conn
    |> write_proxy(client)
    |> read_proxy(client)
  end

  @spec uri(t) :: String.t
  def uri(conn) do
    base = gen_path conn, target_proxy(conn)
    case conn.query_string do
      ""           -> base
      query_string -> ~s(#{base}?#{query_string})
    end
  end

  defp write_proxy(conn, client) do
    case read_body(conn, []) do
      {:ok, body, conn} ->
        :hackney.send_body client, body
        conn
      {:more, body, conn} ->
        :hackney.send_body client, body
        write_proxy conn, client
    end
  end

  defp read_proxy(conn, client) do
    {:ok, status, headers, client} = :hackney.start_response client
    {:ok, body} = :hackney.body client

    headers = List.keydelete headers, "Transfer-Encoding", 0

    cond do
      Record.record? && Play.play? ->
        raise ArgumentError, "Can't set record and play at the same time."
      Play.play? ->
        %{conn | resp_headers: headers}
        |> play_conn
      Record.record? ->
        %{conn | resp_headers: headers}
        |> send_resp(status, body)
        |> Record.record
      true ->
        conn
    end
  end

  defp play_conn(conn) do
    key = String.downcase(conn.method) <> "_" <> Integer.to_string(conn.port) <> conn.request_path

    # TODO: do matching with string ot regex
    # ここでパターンマッチか、完全一致でpathを振り分ける
    case Keyword.get(%Data{}.responses, String.to_atom(key)) do
      {_, resp} ->
        res_json = Map.fetch!(resp, "response")
        response = [
          "body": Map.fetch!(res_json, "body"),
          "cookies": Map.to_list(Map.fetch!(res_json, "cookies")),
          "headers": Map.to_list(Map.fetch!(res_json, "headers"))
                     |> List.insert_at(0, {"Date", conn.resp_headers["Date"]}),
           "status_code": Map.fetch!(res_json, "status_code")
        ]

        conn = %{conn | resp_body: response[:body] }
        conn = %{conn | resp_cookies: response[:cookies] }
        conn = %{conn | status: response[:status_code] }
        conn = %{conn | resp_headers: response[:headers] }
      nil ->
        conn = %{conn | resp_body: "<html>not found nil play_conn case</html>" }
        conn = %{conn | status: 404 }
        conn = %{conn | resp_cookies: [] }
        conn = %{conn | resp_headers: [] }
    end

    send_resp conn, conn.status, conn.resp_body
  end

  defp gen_path(conn, proxy) when proxy == nil do
    case conn.scheme do
      s when s in @scheme ->
        uri = %URI{}
        %URI{uri | scheme: Atom.to_string(conn.scheme), host: conn.host, path: conn.request_path}
        |> URI.to_string
      _ ->
        raise ArgumentError, "no scheme"
    end
  end
  defp gen_path(conn, proxy) do
    uri = URI.parse proxy.to
    %URI{uri | path: conn.request_path}
    |> URI.to_string
  end

  defp target_proxy(conn) do
    Enum.reduce(@proxies, [], fn proxy, acc ->
      cond do
        proxy.port == conn.port ->
          [proxy | acc]
        true ->
          acc
      end
    end)
    |> Enum.at(0)
  end
end

defmodule HttpProxy.Handle do
  @moduledoc """
  Handle every http request to outside of the server.
  """

  use Plug.Builder
  import Plug.Conn
  require Logger

  alias HttpProxy.Play.Data, as: Data
  alias HttpProxy.Record.Response, as: Record
  alias HttpProxy.Play.Response, as: Play

  @proxies Application.get_env :http_proxy, :proxies
  @scheme Application.get_env(:http_proxy, :schemes) || [:http, :https]

  plug Plug.Logger
  plug :dispatch

  # Same as Plug.Conn https://github.com/elixir-lang/plug/blob/576c04c2cba778f1ac9ca28aa71c50efa1046b50/lib/plug/conn.ex#L125
  @type t :: %Plug.Conn{}

  @type param           :: binary | [param]

  @doc """
  Start Cowboy http process with localhost and arbitrary port.
  Clients access to local Cowboy process with HTTP potocol.
  """
  @spec start_link([binary]) :: pid
  def start_link([proxy, module_name]) do
    Logger.info "Running Proxy with Cowboy on http://localhost:#{proxy.port} named #{module_name}"
    Plug.Adapters.Cowboy.http(__MODULE__, [], [port: proxy.port, ref: String.to_atom(module_name)])
  end

  @doc """
  Dispatch connection and Play/Record http/https requests.
  """
  @spec dispatch(t, param) :: t
  def dispatch(conn, _opts) do
    {:ok, client} = String.downcase(conn.method)
                    |> String.to_atom
                    |> :hackney.request(uri(conn), conn.req_headers, :stream, [])
    conn
    |> write_proxy(client)
    |> read_proxy(client)
  end

  @spec uri(t) :: String.t
  def uri(conn) do
    base = gen_path conn, target_proxy(conn)
    case conn.query_string do
      ""           -> base
      query_string -> ~s(#{base}?#{query_string})
    end
  end

  defp write_proxy(conn, client) do
    case read_body(conn, []) do
      {:ok, body, conn} ->
        :hackney.send_body client, body
        conn
      {:more, body, conn} ->
        :hackney.send_body client, body
        write_proxy conn, client
    end
  end

  defp read_proxy(conn, client) do
    {:ok, status, headers, client} = :hackney.start_response client
    {:ok, body} = :hackney.body client

    headers = List.keydelete headers, "Transfer-Encoding", 0

    cond do
      Record.record? && Play.play? ->
        raise ArgumentError, "Can't set record and play at the same time."
      Play.play? ->
        %{conn | resp_headers: headers}
        |> play_conn
      Record.record? ->
        %{conn | resp_headers: headers}
        |> send_resp(status, body)
        |> Record.record
      true ->
        conn
    end
  end

  defp play_conn(conn) do
    key = String.downcase(conn.method) <> "_" <> Integer.to_string(conn.port) <> conn.request_path

    # TODO: do matching with string ot regex
    # ここでパターンマッチか、完全一致でpathを振り分ける
    case Keyword.get(%Data{}.responses, String.to_atom(key), 0) do
      {_, resp} ->
        res_json = Map.fetch!(resp, "response")
        response = [
          "body": Map.fetch!(res_json, "body"),
          "cookies": Map.to_list(Map.fetch!(res_json, "cookies")),
          "headers": Map.to_list(Map.fetch!(res_json, "headers"))
                     |> List.insert_at(0, {"Date", conn.resp_headers["Date"]}),
           "status_code": Map.fetch!(res_json, "status_code")
        ]

        conn = %{conn | resp_body: response[:body] }
        conn = %{conn | resp_cookies: response[:cookies] }
        conn = %{conn | status: response[:status_code] }
        conn = %{conn | resp_headers: response[:headers] }
      nil ->
        conn = %{conn | resp_body: "<html>not found nil play_conn case</html>" }
        conn = %{conn | status: 404 }
        conn = %{conn | resp_cookies: [] }
        conn = %{conn | resp_headers: [] }
    end

    send_resp conn, conn.status, conn.resp_body
  end

  defp gen_path(conn, proxy) when proxy == nil do
    case conn.scheme do
      s when s in @scheme ->
        uri = %URI{}
        %URI{uri | scheme: Atom.to_string(conn.scheme), host: conn.host, path: conn.request_path}
        |> URI.to_string
      _ ->
        raise ArgumentError, "no scheme"
    end
  end
  defp gen_path(conn, proxy) do
    uri = URI.parse proxy.to
    %URI{uri | path: conn.request_path}
    |> URI.to_string
  end

  defp target_proxy(conn) do
    Enum.reduce(@proxies, [], fn proxy, acc ->
      cond do
        proxy.port == conn.port ->
          [proxy | acc]
        true ->
          acc
      end
    end)
    |> Enum.at(0)
  end
end


Increment version [ci skip]

Increment version [ci skip]


Add HTTPoison to dependencies

Add HTTPoison to dependencies


Added phoenix_swagger to compilers (Generate the swagger docs as application get compiled after changes, no need to run mix swagger.)


Added config for mix build

Added config for mix build

defmodule DNS.Mixfile do
  use Mix.Project

  def project do
    [app: :dns,
     version: "0.0.1",
     elixir: "~> 1.4",
     compilers: [:asn1, :erlang] ++ Mix.compilers,
     build_embedded: Mix.env == :prod,
     start_permanent: Mix.env == :prod,
     deps: deps()]
  end

  # Configuration for the OTP application.
  #
  # Type `mix help compile.app` for more information.
  def application do
    [mod: {DNS, []},
     applications: [:base32]]
  end

  # Specifies your project dependencies.
  #
  # Type `mix help deps` for examples and options.
  defp deps do
    [
        {:base32, github: "aetrion/base32_erlang", branch: :master},
        {:asn1ex, github: "T0ha/asn1ex", branch: "master"}
    ]
  end
end

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


start ~/.iex.exs (empty)

start ~/.iex.exs (empty)

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


Add mix format config.

Add mix format config.

[
  # The maximum line length to allow.
  line_length: 80,

  # The files to format by default
  inputs: "{config,lib,test}/**/*.{ex,exs}",

  # Which libraries should we import formatting rules from.
  # Note: At the time of writing, the released versions of some of these do not
  # expose formatting rules.
  import_deps: [],

  # Which local function calls (that is, calls without a module name) should not
  # be parenthesised.
  locals_without_parens: [ ]
]

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


fix onvif unit tests

fix onvif unit tests


Remove hardcoded list of cameras

Remove hardcoded list of cameras


Fix proper bucket name

Fix proper bucket name


Rename var appropriately

Rename var appropriately

defmodule Hound.Helpers.Page do

  import Hound.RequestUtils

  @doc "Gets the HTML source of current page."
  @spec page_source() :: String.t
  def page_source do
    session_id = Hound.current_session_id
    make_req(:get, "session/#{session_id}/source")
  end

  @doc "Gets the title of the current page."
  @spec page_title() :: String.t
  def page_title do
    session_id = Hound.current_session_id
    make_req(:get, "session/#{session_id}/title")
  end

  @doc """
  Finds element on current page. It returns an element ID that can be used with other element functions.

  * The first argument is the strategy.
  * The second argument is the selector.

  Valid selector strategies are `:css`, `:class`, `:id`, `:name`, `:tag`, `:xpath`, `:link_text` and `:partial_link_text`

      find_element(:name, "username")
      find_element(:class, "example")
      find_element(:id, "example")
      find_element(:css, ".example")
      find_element(:tag, "footer")
      find_element(:link_text, "Home")
  """
  @spec find_element(String.t, String.t, Integer.t) :: Dict.t
  def find_element(strategy, selector, retries \\ 5) do
    session_id = Hound.current_session_id
    params = %{using: Hound.InternalHelpers.selector_strategy(strategy), value: selector}

    case make_req(:post, "session/#{session_id}/element", params, %{}, retries*2) do
      %{"ELEMENT" => element_id} ->
        element_id
      value ->
        value
    end
  end

  @doc """
  Finds elements on current page. Returns an array of element IDs that can be used with other element functions.

  * The first argument is the strategy.
  * The second argument is the selector.

  Valid selector strategies are `:css`, `:class`, `:id`, `:name`, `:tag`, `:xpath`, `:link_text` and `:partial_link_text`

      find_elements(:name, "username")
      find_elements(:class, "example")
      find_elements(:id, "example")
      find_elements(:css, ".example")
      find_elements(:tag, "footer")
      find_elements(:link_text, "Home")
  """
  @spec find_all_elements(atom, String.t, Integer.t) :: List.t
  def find_all_elements(strategy, selector, retries \\ 5) do
    session_id = Hound.current_session_id
    params = %{using: Hound.InternalHelpers.selector_strategy(strategy), value: selector}

    case make_req(:post, "session/#{session_id}/elements", params, %{}, retries*2) do
      {:error, value} ->
        {:error, value}
      elements ->
        Enum.map(elements, fn(%{"ELEMENT" => element_id})->
          element_id
        end)
    end
  end

  @doc """
  Finds element within a specific element. Returns an element ID to use with element helper functions.

  * The first argument is the element ID of the element within which you want to search.
  * The second argument is the strategy.
  * The third argument is the selector.

  Valid selector strategies are `:css`, `:class`, `:id`, `:name`, `:tag`, `:xpath`, `:link_text` and `:partial_link_text`

      # First get an element ID to search within
      parent_element_id = find_element(:class, "container")

      find_within_element(parent_element_id, :name, "username")
      find_within_element(parent_element_id, :class, "example")
      find_within_element(parent_element_id, :id, "example")
      find_within_element(parent_element_id, :css, ".example")
      find_within_element(parent_element_id, :tag, "footer")
      find_within_element(parent_element_id, :link_text, "Home")
  """
  @spec find_within_element(String.t, atom, String.t, Integer.t) :: Dict.t
  def find_within_element(element_id, strategy, selector, retries \\ 5) do
    session_id = Hound.current_session_id
    params = %{using: Hound.InternalHelpers.selector_strategy(strategy), value: selector}

    case make_req(:post, "session/#{session_id}/element/#{element_id}/element", params, %{}, retries*2) do
      %{"ELEMENT" => element_id} ->
        element_id
      value ->
        value
    end
  end

  @doc """
  Finds elements within a specific element. Returns an array of element IDs that can be used with other element functions.

  * The first argument is the element ID of the element within which you want to search.
  * The second argument is the strategy.
  * The third argument is the selector.

  Valid selector strategies are `:css`, `:class`, `:id`, `:name`, `:tag`, `:xpath`, `:link_text` and `:partial_link_text`

      # First get an element ID to search within
      parent_element_id = find_element(:class, "container")

      find_all_within_element(parent_element_id, :name, "username")
      find_all_within_element(parent_element_id, :class, "example")
      find_all_within_element(parent_element_id, :id, "example")
      find_all_within_element(parent_element_id, :css, ".example")
      find_all_within_element(parent_element_id, :tag, "footer")
      find_all_within_element(parent_element_id, :link_text, "Home")
  """
  @spec find_all_within_element(String.t, atom, String.t, Integer.t) :: List.t
  def find_all_within_element(element_id, strategy, selector, retries \\ 5) do
    session_id = Hound.current_session_id
    params = %{using: Hound.InternalHelpers.selector_strategy(strategy), value: selector}

    case make_req(:post, "session/#{session_id}/element/#{element_id}/elements", params, %{}, retries*2) do
      {:error, value} ->
        {:error, value}
      elements ->
        Enum.map(elements, fn(%{"ELEMENT" => element_id})->
          element_id
        end)
    end
  end

  @doc "Gets element on page that is currently in focus."
  @spec element_in_focus() :: Dict.t
  def element_in_focus do
    session_id = Hound.current_session_id
    case make_req(:post, "session/#{session_id}/element/active") do
      %{"ELEMENT" => element_id} ->
        element_id
      value ->
        value
    end
  end

  @doc """
  Holds on to the spcified modifier keys when the block is executing.

      # Simulates Ctrl + e
      with_keys :control do
        send_text "e"
      end

      # Simulates Ctrl + Shift + e
      with_keys [:control, :shift] do
        send_text "e"
      end

  The following are the modifier keys:

  * :alt - alt key
  * :shift - shift key
  * :command - command key (or meta key)
  * :control - control key
  * :escape - escape key
  """
  defmacro with_keys(keys, blocks) do
    do_block = Keyword.get(blocks, :do, nil)
    quote do
      send_keys(unquote(keys))
      unquote(do_block)
      send_keys(:null)
    end
  end

  @doc """
  Send sequence of key strokes to active element.
  The keys are accepted as a list of atoms.

      send_keys :backspace
      send_keys :tab

  If you send the modifier keys shift, control, alt and command,
  they are held on and not released until you send the `:null` key.

  To perform other actions while holding on to modifier keys, use the `with_keys` macro.

  The following are the atoms representing the keys:

  * :alt - alt key
  * :shift - shift key
  * :command - command key (or meta key)
  * :control - control key
  * :escape - escape key
  * :backspace - backspace key
  * :tab - tab key
  * :clear - clear
  * :return - return key
  * :enter - enter key
  * :cancel - cancel key
  * :help - help key
  * :pause - pause key
  * :num0 - numpad 0
  * :num1 - numpad 1
  * :num2 - numpad 2
  * :num3 - numpad 3
  * :num4 - numpad 4
  * :num5 - numpad 5
  * :num6 - numpad 6
  * :num7 - numpad 7
  * :num8 - numpad 8
  * :num9 - numpad 9
  * :add - add key
  * :subtract - subtract key
  * :multiply - multiply key
  * :divide - divide key
  * :seperator - seperator key
  """
  @spec send_keys(List.t | atom) :: :ok
  def send_keys(keys) do
    if is_atom(keys), do: keys = [keys]
    session_id = Hound.current_session_id
    make_req(:post,
      "session/#{session_id}/keys",
      Hound.InternalHelpers.key_codes_json(keys),
      %{json_encode: false})
  end

  @doc """
  Send character keys to active element.

      send_text "test"
      send_text "whatever happens"

  To send key strokes like tab, enter, etc, take a look at `send_keys`.
  """
  @spec send_text(String.t) :: :ok
  def send_text(keys) do
    session_id = Hound.current_session_id
    make_req(:post, "session/#{session_id}/keys", %{value: [keys]})
  end
end

defmodule Hound.Helpers.Page do

  import Hound.RequestUtils

  @doc "Gets the HTML source of current page."
  @spec page_source() :: String.t
  def page_source do
    session_id = Hound.current_session_id
    make_req(:get, "session/#{session_id}/source")
  end

  @doc "Gets the title of the current page."
  @spec page_title() :: String.t
  def page_title do
    session_id = Hound.current_session_id
    make_req(:get, "session/#{session_id}/title")
  end

  @doc """
  Finds element on current page. It returns an element ID that can be used with other element functions.

  * The first argument is the strategy.
  * The second argument is the selector.

  Valid selector strategies are `:css`, `:class`, `:id`, `:name`, `:tag`, `:xpath`, `:link_text` and `:partial_link_text`

      find_element(:name, "username")
      find_element(:class, "example")
      find_element(:id, "example")
      find_element(:css, ".example")
      find_element(:tag, "footer")
      find_element(:link_text, "Home")
  """
  @spec find_element(String.t, String.t, Integer.t) :: Dict.t
  def find_element(strategy, selector, timeout_in_seconds \\ 5) do
    session_id = Hound.current_session_id
    params = %{using: Hound.InternalHelpers.selector_strategy(strategy), value: selector}

    case make_req(:post, "session/#{session_id}/element", params, %{}, timeout_in_seconds*2) do
      %{"ELEMENT" => element_id} ->
        element_id
      value ->
        value
    end
  end

  @doc """
  Finds elements on current page. Returns an array of element IDs that can be used with other element functions.

  * The first argument is the strategy.
  * The second argument is the selector.

  Valid selector strategies are `:css`, `:class`, `:id`, `:name`, `:tag`, `:xpath`, `:link_text` and `:partial_link_text`

      find_elements(:name, "username")
      find_elements(:class, "example")
      find_elements(:id, "example")
      find_elements(:css, ".example")
      find_elements(:tag, "footer")
      find_elements(:link_text, "Home")
  """
  @spec find_all_elements(atom, String.t, Integer.t) :: List.t
  def find_all_elements(strategy, selector, timeout_in_seconds \\ 5) do
    session_id = Hound.current_session_id
    params = %{using: Hound.InternalHelpers.selector_strategy(strategy), value: selector}

    case make_req(:post, "session/#{session_id}/elements", params, %{}, timeout_in_seconds*2) do
      {:error, value} ->
        {:error, value}
      elements ->
        Enum.map(elements, fn(%{"ELEMENT" => element_id})->
          element_id
        end)
    end
  end

  @doc """
  Finds element within a specific element. Returns an element ID to use with element helper functions.

  * The first argument is the element ID of the element within which you want to search.
  * The second argument is the strategy.
  * The third argument is the selector.

  Valid selector strategies are `:css`, `:class`, `:id`, `:name`, `:tag`, `:xpath`, `:link_text` and `:partial_link_text`

      # First get an element ID to search within
      parent_element_id = find_element(:class, "container")

      find_within_element(parent_element_id, :name, "username")
      find_within_element(parent_element_id, :class, "example")
      find_within_element(parent_element_id, :id, "example")
      find_within_element(parent_element_id, :css, ".example")
      find_within_element(parent_element_id, :tag, "footer")
      find_within_element(parent_element_id, :link_text, "Home")
  """
  @spec find_within_element(String.t, atom, String.t, Integer.t) :: Dict.t
  def find_within_element(element_id, strategy, selector, timeout_in_seconds \\ 5) do
    session_id = Hound.current_session_id
    params = %{using: Hound.InternalHelpers.selector_strategy(strategy), value: selector}

    case make_req(:post, "session/#{session_id}/element/#{element_id}/element", params, %{}, timeout_in_seconds*2) do
      %{"ELEMENT" => element_id} ->
        element_id
      value ->
        value
    end
  end

  @doc """
  Finds elements within a specific element. Returns an array of element IDs that can be used with other element functions.

  * The first argument is the element ID of the element within which you want to search.
  * The second argument is the strategy.
  * The third argument is the selector.

  Valid selector strategies are `:css`, `:class`, `:id`, `:name`, `:tag`, `:xpath`, `:link_text` and `:partial_link_text`

      # First get an element ID to search within
      parent_element_id = find_element(:class, "container")

      find_all_within_element(parent_element_id, :name, "username")
      find_all_within_element(parent_element_id, :class, "example")
      find_all_within_element(parent_element_id, :id, "example")
      find_all_within_element(parent_element_id, :css, ".example")
      find_all_within_element(parent_element_id, :tag, "footer")
      find_all_within_element(parent_element_id, :link_text, "Home")
  """
  @spec find_all_within_element(String.t, atom, String.t, Integer.t) :: List.t
  def find_all_within_element(element_id, strategy, selector, timeout_in_seconds \\ 5) do
    session_id = Hound.current_session_id
    params = %{using: Hound.InternalHelpers.selector_strategy(strategy), value: selector}

    case make_req(:post, "session/#{session_id}/element/#{element_id}/elements", params, %{}, timeout_in_seconds*2) do
      {:error, value} ->
        {:error, value}
      elements ->
        Enum.map(elements, fn(%{"ELEMENT" => element_id})->
          element_id
        end)
    end
  end

  @doc "Gets element on page that is currently in focus."
  @spec element_in_focus() :: Dict.t
  def element_in_focus do
    session_id = Hound.current_session_id
    case make_req(:post, "session/#{session_id}/element/active") do
      %{"ELEMENT" => element_id} ->
        element_id
      value ->
        value
    end
  end

  @doc """
  Holds on to the spcified modifier keys when the block is executing.

      # Simulates Ctrl + e
      with_keys :control do
        send_text "e"
      end

      # Simulates Ctrl + Shift + e
      with_keys [:control, :shift] do
        send_text "e"
      end

  The following are the modifier keys:

  * :alt - alt key
  * :shift - shift key
  * :command - command key (or meta key)
  * :control - control key
  * :escape - escape key
  """
  defmacro with_keys(keys, blocks) do
    do_block = Keyword.get(blocks, :do, nil)
    quote do
      send_keys(unquote(keys))
      unquote(do_block)
      send_keys(:null)
    end
  end

  @doc """
  Send sequence of key strokes to active element.
  The keys are accepted as a list of atoms.

      send_keys :backspace
      send_keys :tab

  If you send the modifier keys shift, control, alt and command,
  they are held on and not released until you send the `:null` key.

  To perform other actions while holding on to modifier keys, use the `with_keys` macro.

  The following are the atoms representing the keys:

  * :alt - alt key
  * :shift - shift key
  * :command - command key (or meta key)
  * :control - control key
  * :escape - escape key
  * :backspace - backspace key
  * :tab - tab key
  * :clear - clear
  * :return - return key
  * :enter - enter key
  * :cancel - cancel key
  * :help - help key
  * :pause - pause key
  * :num0 - numpad 0
  * :num1 - numpad 1
  * :num2 - numpad 2
  * :num3 - numpad 3
  * :num4 - numpad 4
  * :num5 - numpad 5
  * :num6 - numpad 6
  * :num7 - numpad 7
  * :num8 - numpad 8
  * :num9 - numpad 9
  * :add - add key
  * :subtract - subtract key
  * :multiply - multiply key
  * :divide - divide key
  * :seperator - seperator key
  """
  @spec send_keys(List.t | atom) :: :ok
  def send_keys(keys) do
    if is_atom(keys), do: keys = [keys]
    session_id = Hound.current_session_id
    make_req(:post,
      "session/#{session_id}/keys",
      Hound.InternalHelpers.key_codes_json(keys),
      %{json_encode: false})
  end

  @doc """
  Send character keys to active element.

      send_text "test"
      send_text "whatever happens"

  To send key strokes like tab, enter, etc, take a look at `send_keys`.
  """
  @spec send_text(String.t) :: :ok
  def send_text(keys) do
    session_id = Hound.current_session_id
    make_req(:post, "session/#{session_id}/keys", %{value: [keys]})
  end
end


[major] 0.3.0 release version

[major] 0.3.0 release version


add exrm

add exrm

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/gtcode/phoenix-trello.git/'


dont remove required employee_type for employee_update endpoint (#623)


Added functionality to create thumbnail first and fast


uses logger to announce startup

uses logger to announce startup

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/elixytics/monolith.git/'


Add automatic Login after sign-up

Add automatic Login after sign-up

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/jaysoifer/jonathansoifer.com.git/'


Return an empty list of PTZ presets in case of an error


Fix test snapshot by changing params

Fix test snapshot by changing params


more attribues

more attribues

defmodule Example do

  @attr "one"
  def first, do: @attr

  @attr "two"
  def second, do: @attr

end

IO.puts "#{Example.first} #{Example.second}"

error: pathspec 'elixir/64.ex' did not match any file(s) known to git


add raxx test from project

add raxx test from project

defmodule Raxx.Test do
  def get(path) do
    path = split_path(path)
    %Raxx.Request{path: path}
  end

  def post(path, params) do
    # TODO ensure param keys are strings
    path = split_path(path)
    %Raxx.Request{
      method: "POST",
      path: path,
      body: params
    }
  end

  def patch(path, body) do
    # TODO ensure param keys are strings
    path = split_path(path)
    %Raxx.Request{
      method: "PATCH",
      path: path,
      body: body
    }
  end

  def split_path(str) do
    str
    |> String.split("/")
    |> Enum.reject(&empty_string?/1)

  end

  defp empty_string?("") do
    true
  end
  defp empty_string?(str) when is_binary(str) do
    false
  end
end

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


Start of the browserstack screenshot functionality.

defmodule Vutuv.Browserstack do
  import Ecto.Query
  alias Vutuv.Screenshot
  alias Vutuv.Url
  alias Vutuv.Repo

  def store_screenshot(url) do
    job_id = job_id(url)
    :timer.sleep(30000)
    image_url = image_url(job_id)
    image_url
  end

  def job_id(url) do
    hackney = [basic_auth: {Application.fetch_env!(:vutuv, Vutuv.Endpoint)[:browserstack_user], Application.fetch_env!(:vutuv, Vutuv.Endpoint)[:browserstack_password]}]
    headers = ["Content-Type": "application/json", "Accept": "Application/json; Charset=utf-8"]

    case HTTPoison.post "https://www.browserstack.com/screenshots", "{\"browsers\": [{\"os\": \"Windows\", \"os_version\": \"10\", \"browser_version\": \"50.0\", \"browser\": \"chrome\", \"orientation\": \"landscape\"}], \"url\": \"#{url.value}\"}", headers, [ hackney: hackney ] do
      {:ok, %HTTPoison.Response{status_code: 404}} -> nil
      {:ok, %HTTPoison.Response{body: body, headers: headers}} ->
        decoded_body = body |> Poison.decode!
        {:ok, job_id} = Map.fetch(decoded_body, "job_id")
        job_id
      _ -> nil
    end
  end

  def image_url(job_id) do
    hackney = [basic_auth: {Application.fetch_env!(:vutuv, Vutuv.Endpoint)[:browserstack_user], Application.fetch_env!(:vutuv, Vutuv.Endpoint)[:browserstack_password]}]

    case HTTPoison.get("https://www.browserstack.com/screenshots/#{job_id}.json", %{},[ hackney: hackney ]) do
      {:ok, %HTTPoison.Response{status_code: 404}} -> nil
      {:ok, %HTTPoison.Response{body: body, headers: headers}} ->
         decoded_body = body |> Poison.decode!
         {:ok, results} = Map.fetch(decoded_body, "screenshots")
         {:ok, image_url} = Map.fetch(List.first(results), "image_url")
         image_url
      _ -> nil
    end
  end

  # def store_gravatar(user) do
  #   case HTTPoison.get("https://www.gravatar.com/avatar/#{hd(user.emails).md5sum}?s=130&d=404", [], [timeout: 1000, recv_timeout: 1000])  do
  #     {:ok, %HTTPoison.Response{status_code: 404}} -> nil
  #     {:ok, %HTTPoison.Response{body: body, headers: headers}} ->
  #       content_type = find_content_type(headers)
  #       filename = "/#{user.active_slug}.#{String.replace(content_type,"image/", "")}"
  #       path = System.tmp_dir
  #       upload = #create the upload struct that arc-ecto will use to store the file and update the database
  #         %Plug.Upload{content_type: content_type,
  #         filename: filename,
  #         path: path<>filename}
  #       File.write(path<>filename, body) #Write the file temporarily to the disk
  #       user
  #       |> Repo.preload([:slugs, :oauth_providers, :emails])
  #       |> User.changeset(%{avatar: upload}) #update the user with the upload struct
  #       |> Repo.update
  #     _ -> nil
  #   end
  # end

end

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


Add dataloader debug info (#4029)

Add dataloader debug info (#4029)


Update static/vendors/ace-builds/demo/kitchen-sink/docs/elixir.ex

Signed-off-by: Bernard Ojengwa <fccb4cc00c1ba7e51bf5c2b5f77130b9fe8d917e@gmail.com>

defmodule HelloModule do
  @moduledoc """
    This is supposed to be `markdown`.
    __Yes__ this is [mark](http://down.format)

    # Truly

    ## marked

    * with lists
    * more
    * and more

        Even.with(code)
        blocks |> with |> samples

    _Docs are first class citizens in Elixir_ (Jose Valim)
  """

  # A "Hello world" function
  def some_fun do
    IO.puts "Juhu Kinners!"
  end
  # A private function
  defp priv do
    is_regex ~r"""
       This is a regex
       spanning several
       lines.
    """
    x = elem({ :a, :b, :c }, 0)  #=> :a
  end
end

test_fun = fn(x) ->
  cond do
    x > 10 ->
      :greater_than_ten
    true ->
      :maybe_ten
  end
end

error: pathspec 'static/vendors/ace-builds/demo/kitchen-sink/docs/elixir.ex' did not match any file(s) known to git


[runtime] add pidfile manager

[runtime] add pidfile manager

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


fixed issue with show not working, problem was database expected datetime, when I thought it expected date, solution was to change db to date

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


Add integration test for standard application

defmodule IntegrationTest do
  use ExUnit.Case, async: false

  alias Mix.Releases.Utils

  @standard_app_path Path.join([__DIR__, "fixtures", "standard_app"])
  @standard_output_path Path.join([__DIR__, "fixtures", "standard_app", "rel", "standard_app"])
  @umbrella_app_path Path.join([__DIR__, "fixtures", "umbrella_app"])

  defmacrop with_app(body) do
    quote do
      old_dir = File.cwd!
      File.cd!(@standard_app_path)
      unquote(body)
      File.cd!(old_dir)
    end
  end

  describe "standard application" do
    @tag :expensive
    @tag timeout: 120_000 # 2m
    test "can build release and start it" do
      with_app do
        # Build release
        {:ok, _} = File.rm_rf(Path.join(@standard_app_path, "_build"))
        _ = File.rm(Path.join(@standard_app_path, "mix.lock"))
        :ok = mix("deps.get")
        :ok = mix("deps.compile", ["distillery"])
        :ok = mix("compile")
        :ok = mix("release.clean")
        result = mix("release", ["--verbose", "--env=prod"])
        r = case result do
          :ok -> :ok
          {:error, _code, output} ->
            IO.puts(output)
            :error
        end
        assert :ok = r
        assert ["0.0.1"] == Utils.get_release_versions(@standard_output_path)
        # Boot it, ping it, and shut it down
        bin_path = Path.join([@standard_output_path, "bin", "standard_app"])
        assert File.exists?(bin_path)
        assert {_output, 0} = System.cmd(bin_path, ["start"])
        :timer.sleep(1_000) # Required, since starting up takes a sec
        assert {output, 0} = System.cmd(bin_path, ["ping"])
        assert String.contains?(output, "pong")
        assert {output, 0} = System.cmd(bin_path, ["stop"])
        assert String.contains?(output, "ok")
        sys_config_path = Path.join([@standard_output_path, "releases", "0.0.1", "sys.config"])
        assert {:ok, [sysconfig_content]} = Utils.read_terms(sys_config_path)
        assert 2 = get_in(sysconfig_content, [:standard_app, :num_procs])
      end
    end
  end

  # Call the elixir mix binary with the given arguments
  defp mix(command),       do: do_cmd(:prod, command)
  defp mix(command, args), do: do_cmd(:prod, command, args)

  defp do_cmd(env, command, args \\ []) do
    case System.cmd "mix", [command|args], env: [{"MIX_ENV", "#{env}"}] do
      {_output, 0} -> :ok
      {output, err} -> {:error, err, output}
    end
  end
end

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


[feat] add sites schema

[feat] add sites schema

defmodule SituationRoom.Site do
  use Ecto.Schema

  schema "sites" do
    field :endpoint, :string
    field :name, :string
  end
end

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


Revert "Added old values for max connections and timeout" (#548)

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


Return empty array in case of no archive


Extract pull request related db queries into StoredPullRequests module

defmodule Pullhub.StoredPullRequests do
  import Ecto.Query

  alias Pullhub.PullRequest
  alias Pullhub.Repo
  alias Pullhub.Repository

  def insert_pull_requests(pull_requests, %Repository{id: repo_id}) do
    pull_requests
    |> Enum.map(&add_repository_id_to_pull_request(&1, repo_id))
    |> insert_pull_requests
  end

  def pull_requests(%Repository{id: repo_id}) do
    from p in PullRequest, where: p.repository_id == ^repo_id
  end

  defp insert_pull_requests(pulls) do
    pulls
    |> Enum.map(fn(pull) -> Repo.insert(pull) end)
  end

  def remove_pull_requests(%Repository{id: repo_id} = repo) do
    pull_requests(repo)
    |> Repo.delete_all
  end

  defp add_repository_id_to_pull_request(%PullRequest{} = pull, repo_id) do
    %{ pull | repository_id: repo_id }
  end
end

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


add StringsAndBinaries-6

add StringsAndBinaries-6

defmodule MyString6 do
  @delim ". "
  def capitalize_sentences(dqs), do: Enum.map(String.split(dqs, @delim), &String.capitalize(&1)) |> Enum.join(@delim)
end

IO.puts MyString6.capitalize_sentences("oh. A DOG. woof. ") # Oh. A dog. Woof.

error: pathspec 'lib/StringsAndBinaries-6/capitalize.ex' did not match any file(s) known to git


Change vote unique index

Change vote unique index

defmodule Api.Repo.Migrations.ChangeVoteUniqueIndex do
  use Ecto.Migration

  def change do
    drop unique_index(:votes, [:voter_identity])
    create unique_index(:votes, [:voter_identity, :category_id])
  end
end

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


fix ContractRequest filter by assignee name test

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/'


Fix schedule check when updating thumbnail

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/'


(8.2%) test handling of deleted assets when auto_sync is disabled

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


Add arguments migration

Add arguments migration

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


fix medication_request employee_id filter


update not_thumbnailed indices

update not_thumbnailed indices

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


Removed unused Ecto.Query

Removed unused Ecto.Query

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


skip tests tagged with :skip

skip tests tagged with :skip


Add tests for `Serum.Util` module

Add tests for `Serum.Util` module

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


chore: match pattern of Map

chore: match pattern of Map

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/rockdragon/julia-programming.git/'


Set timeout and pool_timeout for both databases


Increment version [ci skip]

Increment version [ci skip]

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


Increment version [ci skip]

Increment version [ci skip]


Tweak error code weights

Tweak error code weights


Added case for %UndefinedFunctionError{}.


list operations

list operations

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


chore: exception

chore: exception


Add Table.

Add Table.

defmodule Wobserver.Table do
  @moduledoc ~S"""
  Table

  TODO:
    - Needs docs.
    - Needs cleanup.
    - Needs tests.
  """

  @spec list :: list(map)
  def list do
    :ets.all
    |> Enum.map(&info/1)
  end

  @spec info(table :: atom | integer, include_data :: boolean) :: map
  def info(table, include_data \\ false)

  def info(table, false) do
    %{
      id: table,
      name: :ets.info(table, :name),
      type: :ets.info(table, :type),
      size: :ets.info(table, :size),
      memory: :ets.info(table, :memory),
      owner: :ets.info(table, :owner),
      protection: :ets.info(table, :protection),
      meta: %{
        read_concurrency: :ets.info(table, :read_concurrency),
        write_concurrency: :ets.info(table, :write_concurrency),
        compressed: :ets.info(table, :compressed),
      },
    }
  end

  def info(table, true) do
    %{
      id: table,
      name: :ets.info(table, :name),
      type: :ets.info(table, :type),
      size: :ets.info(table, :size),
      memory: :ets.info(table, :memory),
      owner: :ets.info(table, :owner),
      protection: :ets.info(table, :protection),
      data: data(table),
      meta: %{
        read_concurrency: :ets.info(table, :read_concurrency),
        write_concurrency: :ets.info(table, :write_concurrency),
        compressed: :ets.info(table, :compressed),
      },
    }
  end

  @spec sanitize(table :: atom | integer | String.t) :: atom | integer
  def sanitize(table) when is_atom(table), do: table
  def sanitize(table) when is_integer(table), do: table
  def sanitize(table) when is_binary(table) do
    case Integer.parse(table) do
      {nr, ""} -> nr
      _ -> table |> Wobserver.Util.Process.string_to_module
    end
  end

  defp data(table) do
    case :ets.info(table, :protection) do
      :private ->
        []
      _ ->
        table
        |> :ets.match(:"$1")
        |> Enum.map(&data_row/1)
    end
  end

  defp data_row([row]) do
    row
    |> Tuple.to_list
    |> Enum.map(&(to_string(:io_lib.format("~tp", [&1]))))
  end
end

error: pathspec 'lib/wobserver/util/table.ex' did not match any file(s) known to git


do not update permanent keys on employee_request approve (#618)


fix contract_request migration with default value for contract_type (#3564)


chore: get in nested data

chore: get in nested data


declaration_request indexes migration fixed (#4071)


Small grammar fix

Small grammar fix

defmodule OptionParser do
  @moduledoc """
  This module contains functions to parse command line arguments.
  """

  @doc """
  Parses `argv` and returns a tuple with the parsed options, its
  arguments, and a list of options that couldn't be parsed.

  ## Examples

      iex> OptionParser.parse(["--debug"])
      { [debug: true], [], [] }

      iex> OptionParser.parse(["--source", "lib"])
      { [source: "lib"], [], [] }

      iex> OptionParser.parse(["--source-path", "lib", "test/enum_test.exs", "--verbose"])
      { [source_path: "lib", verbose: true], ["test/enum_test.exs"], [] }

  Notice how Elixir automatically translates the "--source-path"
  switch to the underscored atom `:source_path`, which better follows
  Elixir conventions.

  ## Aliases

  A set of aliases can be given as the second argument:

      iex> OptionParser.parse(["-d"], aliases: [d: :debug])
      { [debug: true], [], [] }

  ## Switches

  Extra information about switches can be given as arguments, too.
  This is useful when a switch must behave as a boolean
  or if duplicated switches should be kept, overridden or accumulated.

  The following types are supported:

  * `:boolean` - Marks the given switch as a boolean. Boolean switches
                 never consume the following value unless it is
                 `true` or `false`;
  * `:integer` - Parses the switch as an integer;
  * `:float`   - Parses the switch as a float;
  * `:string`  - Returns the switch as is (the default);

  If a switch can't be parsed, the option is returned in the invalid
  options list (third element of the returned tuple).

  The following extra options are supported:

  * `:keep` - Keeps duplicated items in the list instead of overriding;

  Examples:

      iex> OptionParser.parse(["--unlock", "path/to/file"], switches: [unlock: :boolean])
      { [unlock: true], ["path/to/file"], [] }

      iex> OptionParser.parse(["--unlock", "--limit", "0", "path/to/file"],
      ...>                    switches: [unlock: :boolean, limit: :integer])
      { [unlock: true, limit: 0], ["path/to/file"], [] }

      iex> OptionParser.parse(["--limit", "3"], switches: [limit: :integer])
      { [limit: 3], [], [] }

      iex> OptionParser.parse(["--limit", "yyz"], switches: [limit: :integer])
      { [], [], [limit: "yyz"] }

  ## Negation switches

  Any switches starting with `--no-` are always considered to be
  booleans and never parse the next value:

      iex> OptionParser.parse(["--no-op", "path/to/file"])
      { [no_op: true], ["path/to/file"], [] }

  In case the negated switch exists as a boolean, it sets the boolean to false:

      iex> OptionParser.parse(["--no-op", "path/to/file"], switches: [op: :boolean])
      { [op: false], ["path/to/file"], [] }

  """
  def parse(argv, opts \\ []) when is_list(argv) and is_list(opts) do
    parse(argv, opts, true)
  end

  @doc """
  Similar to `parse/2` but only parses the head of `argv`;
  as soon as it finds a non-switch, it stops parsing.

  See `parse/2` for more information.

  ## Example

      iex> OptionParser.parse_head(["--source", "lib", "test/enum_test.exs", "--verbose"])
      { [source: "lib"], ["test/enum_test.exs", "--verbose"], [] }

      iex> OptionParser.parse_head(["--verbose", "--source", "lib", "test/enum_test.exs", "--unlock"])
      { [verbose: true, source: "lib"], ["test/enum_test.exs", "--unlock"], [] }

  """
  def parse_head(argv, opts \\ []) when is_list(argv) and is_list(opts) do
    parse(argv, opts, false)
  end

  ## Helpers

  defp parse(argv, opts, bool) do
    aliases  = opts[:aliases]  || []
    switches = opts[:switches] || []
    parse(argv, aliases, switches, bool)
  end

  defp parse(argv, aliases, switches, all) do
    parse(argv, aliases, switches, [], [], [], all)
  end

  defp parse(["--"|_] = value, _aliases, _switches, dict, _args, invalid, _all) do
    { Enum.reverse(dict), value, Enum.reverse(invalid) }
  end

  defp parse(["-" <> option|t], aliases, switches, dict, args, invalid, all) do
    { option, value } = split_option(option)
    { option, kinds, value } = normalize_option(option, value, switches, aliases)

    if nil?(value) do
      { value, t } =
        if :boolean in kinds do
          { true, t }
        else
          value_from_tail(t)
        end
    end

    { dict, invalid } = store_option(dict, invalid, option, value, kinds)

    parse(t, aliases, switches, dict, args, invalid, all)
  end

  defp parse([h|t], aliases, switches, dict, args, invalid, true) do
    parse(t, aliases, switches, dict, [h|args], invalid, true)
  end

  defp parse([], _, _switches, dict, args, invalid, true) do
    { Enum.reverse(dict), Enum.reverse(args), Enum.reverse(invalid) }
  end

  defp parse(value, _, _switches, dict, _args, invalid, false) do
    { Enum.reverse(dict), value, Enum.reverse(invalid) }
  end

  defp value_from_tail(["-" <> _|_] = t), do: { true, t }
  defp value_from_tail([h|t]),            do: { h, t }
  defp value_from_tail([]),               do: { true, [] }

  defp store_option(dict, invalid, option, value, kinds) do
    { invalid_option, value } =
      cond do
        :invalid in kinds ->
          { option, value }
        :boolean in kinds ->
          { nil, value in [true, "true"] }
        :integer in kinds ->
          case Integer.parse(value) do
            { value, "" } -> { nil, value }
            _ -> { option, value }
          end
        :float in kinds ->
          case Float.parse(value) do
            { value, "" } -> { nil, value }
            _ -> { option, value }
          end
        true ->
          { nil, value }
      end

    if invalid_option do
      { dict, [{ option, value }|invalid] }
    else
      { do_store_option(dict, option, value, kinds), invalid }
    end
  end

  defp do_store_option(dict, option, value, kinds) do
    cond do
      :keep in kinds ->
        [{ option, value }|dict]
      true ->
        [{ option, value }|Keyword.delete(dict, option)]
    end
  end

  defp normalize_option(<<?-, option :: binary>>, value, switches, _aliases) do
    normalize_option(get_negated(option, switches), value, switches)
  end

  defp normalize_option(option, value, switches, aliases) do
    option = get_option(option)
    if alias = aliases[option] do
      normalize_option({ :default, alias }, value, switches)
    else
      { option, [:invalid], value }
    end
  end

  defp normalize_option({ :negated, option }, _value, switches) do
    kinds = List.wrap(switches[option])

    if :boolean in kinds do
      { option, kinds, false }
    else
      { option, [:boolean], true }
    end
  end

  defp normalize_option({ :default, option }, value, switches) do
    { option, List.wrap(switches[option]), value }
  end

  defp split_option(option) do
    case :binary.split(option, "=") do
      [h]    -> { h, nil }
      [h, t] -> { h, t }
    end
  end

  defp to_underscore(option) do
    for <<c <- option>>, into: "", do: << if(c == ?-, do: ?_, else: c) >>
  end

  defp get_option(option) do
    option |> to_underscore |> binary_to_atom
  end

  defp get_negated("no-" <> rest = option, switches) do
    negated = get_option(rest)
    option  = if Keyword.has_key?(switches, negated), do: negated, else: get_option(option)
    { :negated, option }
  end

  defp get_negated(rest, _switches) do
    { :default, get_option(rest) }
  end
end

defmodule OptionParser do
  @moduledoc """
  This module contains functions to parse command line arguments.
  """

  @doc """
  Parses `argv` and returns a tuple with the parsed options, its
  arguments, and a list options that couldn't be parsed.

  ## Examples

      iex> OptionParser.parse(["--debug"])
      { [debug: true], [], [] }

      iex> OptionParser.parse(["--source", "lib"])
      { [source: "lib"], [], [] }

      iex> OptionParser.parse(["--source-path", "lib", "test/enum_test.exs", "--verbose"])
      { [source_path: "lib", verbose: true], ["test/enum_test.exs"], [] }

  Notice how Elixir automatically translates the "--source-path"
  switch to the underscored atom `:source_path`, which better follows
  Elixir conventions.

  ## Aliases

  A set of aliases can be given as the second argument:

      iex> OptionParser.parse(["-d"], aliases: [d: :debug])
      { [debug: true], [], [] }

  ## Switches

  Extra information about switches can be given as arguments, too.
  This is useful when a switch must behave as a boolean
  or if duplicated switches should be kept, overridden or accumulated.

  The following types are supported:

  * `:boolean` - Marks the given switch as a boolean. Boolean switches
                 never consume the following value unless it is
                 `true` or `false`;
  * `:integer` - Parses the switch as an integer;
  * `:float`   - Parses the switch as a float;
  * `:string`  - Returns the switch as is (the default);

  If a switch can't be parsed, the option is returned in the invalid
  options list (third element of the returned tuple).

  The following extra options are supported:

  * `:keep` - Keeps duplicated items in the list instead of overriding;

  Examples:

      iex> OptionParser.parse(["--unlock", "path/to/file"], switches: [unlock: :boolean])
      { [unlock: true], ["path/to/file"], [] }

      iex> OptionParser.parse(["--unlock", "--limit", "0", "path/to/file"],
      ...>                    switches: [unlock: :boolean, limit: :integer])
      { [unlock: true, limit: 0], ["path/to/file"], [] }

      iex> OptionParser.parse(["--limit", "3"], switches: [limit: :integer])
      { [limit: 3], [], [] }

      iex> OptionParser.parse(["--limit", "yyz"], switches: [limit: :integer])
      { [], [], [limit: "yyz"] }

  ## Negation switches

  Any switches starting with `--no-` are always considered to be
  booleans and never parse the next value:

      iex> OptionParser.parse(["--no-op", "path/to/file"])
      { [no_op: true], ["path/to/file"], [] }

  In case the negated switch exists as a boolean, it sets the boolean to false:

      iex> OptionParser.parse(["--no-op", "path/to/file"], switches: [op: :boolean])
      { [op: false], ["path/to/file"], [] }

  """
  def parse(argv, opts \\ []) when is_list(argv) and is_list(opts) do
    parse(argv, opts, true)
  end

  @doc """
  Similar to `parse/2` but only parses the head of `argv`;
  as soon as it finds a non-switch, it stops parsing.

  See `parse/2` for more information.

  ## Example

      iex> OptionParser.parse_head(["--source", "lib", "test/enum_test.exs", "--verbose"])
      { [source: "lib"], ["test/enum_test.exs", "--verbose"], [] }

      iex> OptionParser.parse_head(["--verbose", "--source", "lib", "test/enum_test.exs", "--unlock"])
      { [verbose: true, source: "lib"], ["test/enum_test.exs", "--unlock"], [] }

  """
  def parse_head(argv, opts \\ []) when is_list(argv) and is_list(opts) do
    parse(argv, opts, false)
  end

  ## Helpers

  defp parse(argv, opts, bool) do
    aliases  = opts[:aliases]  || []
    switches = opts[:switches] || []
    parse(argv, aliases, switches, bool)
  end

  defp parse(argv, aliases, switches, all) do
    parse(argv, aliases, switches, [], [], [], all)
  end

  defp parse(["--"|_] = value, _aliases, _switches, dict, _args, invalid, _all) do
    { Enum.reverse(dict), value, Enum.reverse(invalid) }
  end

  defp parse(["-" <> option|t], aliases, switches, dict, args, invalid, all) do
    { option, value } = split_option(option)
    { option, kinds, value } = normalize_option(option, value, switches, aliases)

    if nil?(value) do
      { value, t } =
        if :boolean in kinds do
          { true, t }
        else
          value_from_tail(t)
        end
    end

    { dict, invalid } = store_option(dict, invalid, option, value, kinds)

    parse(t, aliases, switches, dict, args, invalid, all)
  end

  defp parse([h|t], aliases, switches, dict, args, invalid, true) do
    parse(t, aliases, switches, dict, [h|args], invalid, true)
  end

  defp parse([], _, _switches, dict, args, invalid, true) do
    { Enum.reverse(dict), Enum.reverse(args), Enum.reverse(invalid) }
  end

  defp parse(value, _, _switches, dict, _args, invalid, false) do
    { Enum.reverse(dict), value, Enum.reverse(invalid) }
  end

  defp value_from_tail(["-" <> _|_] = t), do: { true, t }
  defp value_from_tail([h|t]),            do: { h, t }
  defp value_from_tail([]),               do: { true, [] }

  defp store_option(dict, invalid, option, value, kinds) do
    { invalid_option, value } =
      cond do
        :invalid in kinds ->
          { option, value }
        :boolean in kinds ->
          { nil, value in [true, "true"] }
        :integer in kinds ->
          case Integer.parse(value) do
            { value, "" } -> { nil, value }
            _ -> { option, value }
          end
        :float in kinds ->
          case Float.parse(value) do
            { value, "" } -> { nil, value }
            _ -> { option, value }
          end
        true ->
          { nil, value }
      end

    if invalid_option do
      { dict, [{ option, value }|invalid] }
    else
      { do_store_option(dict, option, value, kinds), invalid }
    end
  end

  defp do_store_option(dict, option, value, kinds) do
    cond do
      :keep in kinds ->
        [{ option, value }|dict]
      true ->
        [{ option, value }|Keyword.delete(dict, option)]
    end
  end

  defp normalize_option(<<?-, option :: binary>>, value, switches, _aliases) do
    normalize_option(get_negated(option, switches), value, switches)
  end

  defp normalize_option(option, value, switches, aliases) do
    option = get_option(option)
    if alias = aliases[option] do
      normalize_option({ :default, alias }, value, switches)
    else
      { option, [:invalid], value }
    end
  end

  defp normalize_option({ :negated, option }, _value, switches) do
    kinds = List.wrap(switches[option])

    if :boolean in kinds do
      { option, kinds, false }
    else
      { option, [:boolean], true }
    end
  end

  defp normalize_option({ :default, option }, value, switches) do
    { option, List.wrap(switches[option]), value }
  end

  defp split_option(option) do
    case :binary.split(option, "=") do
      [h]    -> { h, nil }
      [h, t] -> { h, t }
    end
  end

  defp to_underscore(option) do
    for <<c <- option>>, into: "", do: << if(c == ?-, do: ?_, else: c) >>
  end

  defp get_option(option) do
    option |> to_underscore |> binary_to_atom
  end

  defp get_negated("no-" <> rest = option, switches) do
    negated = get_option(rest)
    option  = if Keyword.has_key?(switches, negated), do: negated, else: get_option(option)
    { :negated, option }
  end

  defp get_negated(rest, _switches) do
    { :default, get_option(rest) }
  end
end