Muex.MixBootstrap (Muex v0.13.1)

View Source

Starts Mix and loads the project's mix.exs inside the escript.

An escript carries its own Elixir runtime but not Mix, and it never evaluates the mix.exs of the project it is run in. Muex.CLI therefore starts Mix itself and evaluates the project's mix.exs before anything asks for Mix.Project. This module is that bootstrap, kept apart from the CLI so it can be tested without halting the VM.

Where Mix comes from

The escript embeds Elixir but Mix is loaded from the Elixir installation the elixir executable on PATH belongs to (<elixir>/lib/mix/ebin). The same installation supplies eex and ex_unit, which mix test needs. Mix is loaded at runtime rather than embedded in the escript because it evaluates the mix.exs of the project it runs in, and so belongs to that project's Elixir version, not to the one muex was built with.

A project that cannot supply Mix is refused with an explanation instead of a Mix.start/0 is undefined stack trace.

Loading the project

load_project/1 evaluates mix.exs the way mix itself does, so mix muex and muex see the same project: the same app name, the same umbrella. It does not run loadpaths or compile: Muex.Sandbox is the only part of muex that reads the loaded project, and only for its :app, while every test run compiles in its own sandbox. Running loadpaths here would rewrite the code path for the loaded project, dropping the directory muex itself is running from when that is a _build of another project.

Summary

Types

Why the project could not be loaded.

Functions

The mix.exs at or above dir, or nil when there is none.

Formats an error from load_project/1 as a message for the user.

Starts Mix and loads the project at or above dir.

Starts Mix, evaluating project_file as the current project.

Types

error()

@type error() ::
  {:no_mix, String.t()}
  | {:no_project, Path.t()}
  | {:load_failed, Path.t(), Exception.t()}

Why the project could not be loaded.

  • :no_mix - Mix could not be found next to the elixir on PATH.
  • :no_project - no mix.exs was found at or above the working directory.
  • :load_failed - mix.exs raised while it was evaluated.

Functions

find_project_file(dir)

@spec find_project_file(Path.t()) :: Path.t() | nil

The mix.exs at or above dir, or nil when there is none.

Mirrors how mix finds the project it is run in: the nearest mix.exs walking up from the working directory.

format_error(arg)

@spec format_error(error()) :: String.t()

Formats an error from load_project/1 as a message for the user.

load_project(dir \\ File.cwd!())

@spec load_project(Path.t()) :: :ok | {:error, error()}

Starts Mix and loads the project at or above dir.

dir defaults to the working directory. On success Mix.Project.get/0 returns the project's module and Mix.Project.project_file/0 names its mix.exs, exactly as under mix muex.

start(project_file \\ nil)

@spec start(String.t() | nil) :: :ok | {:error, {:no_mix, String.t()} | error()}

Starts Mix, evaluating project_file as the current project.

When project_file is nil or does not exist, Mix is started but no project is loaded; load_project/1 is the entry point that reports {:no_project, _}.

Returns :ok, {:error, {:no_mix, reason}} when Mix is not available, or {:error, {:load_failed, file, exception}} when mix.exs raises.