Current section

Files

Jump to
igniter_new lib mix tasks igniter.init_library.ex
Raw

lib/mix/tasks/igniter.init_library.ex

defmodule Mix.Tasks.Igniter.InitLibrary do
@moduledoc """
Set up a library to use Igniter. Adds the optional dependency
and an install task.
## Args
mix igniter.init_library my_lib
* `--dry-run` - Run the task without making any changes.
* `--yes` - Automatically answer yes to any prompts.
* `--yes-to-deps` - Automatically answer yes to any prompts about installing new deps.
* `--verbose` - display additional output from various operations
"""
use Mix.Task
@apps [:logger, :public_key, :ssl, :inets, :eex]
@impl true
@shortdoc "Set up a library to use Igniter. Adds the optional dependency and an install task."
def run(argv) do
app_name =
case argv do
[] ->
Mix.shell().error("""
Missing argument: app name
Try running `mix igniter.init_library my_lib`.
""")
exit({:shutdown, 1})
[app_name] ->
app_name
end
archives_path = Mix.path_for(:archives)
archive_apps =
archives_path
|> File.ls()
|> case do
{:ok, entries} ->
entries
_ ->
[]
end
|> Enum.map(&Mix.Local.archive_ebin/1)
|> Enum.map(&Path.join([archives_path, &1, "*.app"]))
|> Enum.flat_map(&Path.wildcard/1)
|> Enum.map(&Path.basename(&1, ".app"))
|> Enum.map(&String.to_atom/1)
for app <- @apps ++ archive_apps do
try do
Mix.ensure_application!(app)
rescue
_ ->
:ok
end
end
message =
cond do
"--igniter-repeat" in argv ->
"setting up igniter"
"--from-igniter-new" in argv ->
"installing igniter"
true ->
"checking for igniter in project"
end
if !Process.get(:updated_igniter?) do
Igniter.Installer.Loading.with_spinner(
"Updating project's igniter dependency",
fn ->
System.cmd("mix", ["deps.update", "igniter"], stderr_to_stdout: true)
end,
verbose?: "--verbose" in argv
)
Process.put(:updated_igniter?, true)
end
Igniter.Installer.Loading.with_spinner(
message,
fn ->
if Code.ensure_loaded?(Igniter.Util.Install) do
Mix.Task.run("deps.loadpaths", ["--no-deps-check"])
end
end,
verbose?: "--verbose" in argv
)
argv = Enum.reject(argv, &(&1 in ["--igniter-repeat", "--from-igniter-new"]))
if File.exists?("mix.exs") do
contents =
"mix.exs"
|> File.read!()
new_contents =
contents
|> add_igniter_dep()
new_contents =
if contents == new_contents do
contents
else
new_contents
|> Code.format_string!()
end
if new_contents == contents && !String.contains?(contents, "{:igniter,") do
Mix.shell().error("""
Failed to add igniter to mix.exs. Please add it manually and try again
For more information, see: https://hexdocs.pm/igniter/readme.html#installation
""")
exit({:shutdown, 1})
else
File.write!("mix.exs", new_contents)
Mix.Project.clear_deps_cache()
Mix.Project.pop()
Mix.Dep.clear_cached()
old_undefined = Code.get_compiler_option(:no_warn_undefined)
old_relative_paths = Code.get_compiler_option(:relative_paths)
old_ignore_module_conflict = Code.get_compiler_option(:ignore_module_conflict)
try do
Code.compiler_options(
relative_paths: false,
no_warn_undefined: :all,
ignore_module_conflict: true
)
_ = Code.compile_file("mix.exs")
after
Code.compiler_options(
relative_paths: old_relative_paths,
no_warn_undefined: old_undefined,
ignore_module_conflict: old_ignore_module_conflict
)
end
Igniter.Installer.Loading.with_spinner(
"compiling igniter",
fn ->
case System.cmd("mix", ["deps.get"]) do
{_, 0} ->
:ok
{output, status} ->
raise("""
mix deps.get failed with exit code #{status}.
Output:
#{output}
""")
end
Mix.Task.reenable("deps.compile")
Mix.Task.reenable("deps.loadpaths")
Mix.Task.run("deps.compile", [])
Mix.Task.run("deps.loadpaths", ["--no-deps-check"])
Mix.Task.reenable("deps.compile")
Mix.Task.reenable("deps.loadpaths")
end,
verbose?: "--verbose" in argv
)
Mix.Task.run("igniter.gen.task", ["#{app_name}.install"])
end
else
Mix.shell().error("""
Not in a mix project. No `mix.exs` file was found.
Did you mean `mix igniter.new`?
""")
exit({:shutdown, 1})
end
end
defp add_igniter_dep(contents) do
version_requirement = "\"~> 0.6\""
if String.contains?(contents, "{:igniter") do
Mix.shell().info("Igniter is already in the project.")
contents
else
add_igniter_dep(contents, version_requirement)
end
end
defp add_igniter_dep(contents, version_requirement) do
if String.contains?(contents, "defp deps do\n []") do
String.replace(
contents,
"defp deps do\n []",
"defp deps do\n [{:igniter, #{version_requirement}, optional: true, runtime: false]"
)
else
String.replace(
contents,
"defp deps do\n [\n",
"defp deps do\n [\n {:igniter, #{version_requirement}, optional: true, runtime: false},\n"
)
end
end
end