Current section
Files
Jump to
Current section
Files
lib/mix/tasks/ip.refresh_scopes.ex
defmodule Mix.Tasks.Ip.RefreshScopes do
@moduledoc """
A mix task which downloads the latest special purpose address registries from
the IANA website and stores them in this package's priv directory.
"""
@shortdoc "Refresh IP scopes up to date"
use Mix.Task
@v4_file "iana-ipv4-special-registry.xml"
@v6_file "iana-ipv6-special-registry.xml"
@v4_url "https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xml"
@v6_url "https://www.iana.org/assignments/iana-ipv6-special-registry/iana-ipv6-special-registry.xml"
@doc false
@impl true
def run(["--check"]) do
v4_path = priv_path(@v4_file)
v6_path = priv_path(@v6_file)
if File.exists?(v4_path) && File.exists?(v6_path) do
do_check(v4_path, v6_path)
else
Mix.shell().error("local registry copies do not exist")
System.stop(1)
end
end
def run([]) do
Application.ensure_all_started(:req)
v4_path = priv_path(@v4_file)
v6_path = priv_path(@v6_file)
with v4_task <- retrieve_v4(),
v6_task <- retrieve_v6(),
{:ok, v4_result} <- Task.await(v4_task),
{:ok, v6_result} <- Task.await(v6_task),
:ok <- File.write(v4_path, v4_result.body),
:ok <- File.write(v6_path, v6_result.body) do
Mix.shell().info("Registry files written")
:ok
else
{:error, reason} -> handle_error(reason)
end
end
def run(args) do
Mix.shell().error("Unknown arguments: `#{inspect(args)}`")
System.stop(1)
end
defp do_check(v4_path, v6_path) do
Application.ensure_all_started(:req)
with {:ok, v4_content} <- File.read(v4_path),
{:ok, v6_content} <- File.read(v6_path),
v4_task <- retrieve_v4(),
v6_task <- retrieve_v6(),
{:ok, v4_result} <- Task.await(v4_task),
{:ok, v6_result} <- Task.await(v6_task) do
if v4_result.body == v4_content && v6_content == v6_result.body do
Mix.shell().info("registry data is up to date")
else
Mix.shell().error("registry data is out of date")
System.stop(1)
end
else
{:error, reason} -> handle_error(reason)
end
end
defp retrieve_v4 do
Task.async(fn ->
Req.get(@v4_url)
end)
end
defp retrieve_v6 do
Task.async(fn ->
Req.get(@v6_url)
end)
end
defp priv_path(path) do
:ip
|> :code.priv_dir()
|> Path.join(path)
end
defp handle_error(error) when is_exception(error) do
error
|> Exception.message()
|> Mix.shell().error()
end
defp handle_error(error) when is_binary(error) do
if String.printable?(error) do
Mix.shell().error(error)
else
Mix.shell().error(inspect(error))
end
end
defp handle_error(error), do: Mix.shell().error(inspect(error))
end