SvelixirNew.Bootstrap (svelixir_new v0.11.0)

Copy Markdown

The mix svelixir.new sequence, with every effect injected.

It lives here rather than in Mix.Tasks.Svelixir.New.run/1 for a coverage reason that is structural, not stylistic: @impl Mix.Task fixes run/1's arity at 1, so there is no parameter through which a fake runner could reach the sequence. Measured with the sequence inlined in run/1, 12 of 14 relevant lines were reachable only from a @tag :toolchain test that ExUnit.start(exclude:) removes from the coverage run, and rescuing them with coveralls-ignore blew the 5% budget several times over.

The call order is load-bearing

The generator probe must precede any dependency work, because mix deps.compile prunes every archive off the code path (Code.delete_paths(current_paths -- loaded_paths)). Measured: archive paths go from three entries to [] across that one call, after which Mix.Task.get("phx.new") returns nil even though phx_new is installed on disk.

Patching and config-writing precede dependency work too, so a project whose mix.exs cannot be patched is never compiled against a dep it does not declare.

Summary

Functions

The real effects.

Runs the bootstrap. See this module's documentation for the ordering rules.

Types

effects()

@type effects() :: %{
  getenv: (-> %{optional(String.t()) => String.t()}),
  lookup: SvelixirNew.Shell.lookup(),
  generator: (String.t(), [String.t()] -> any()),
  runner: SvelixirNew.Shell.runner(),
  shell: module()
}

Functions

defaults()

@spec defaults() :: effects()

The real effects.

run(opts, effects)

@spec run(SvelixirNew.Options.t(), effects()) :: :ok

Runs the bootstrap. See this module's documentation for the ordering rules.