# `MixAffected.Run`
[🔗](https://github.com/mnox/mix_affected/blob/v0.1.0/lib/mix_affected/run.ex#L1)

One selection, end to end: classify the change set, build the graph only if
a source changed, build or read the test map only if anything is affected,
add the map's protocol-impl edges to the graph, then select.

Fail-open rules: a global invalidation or an unmapped file is a full run
(exit status 0); a graph or test map that cannot be built is a full run with
exit status 2 (`graph_unavailable:<detail>`, `test_map_unavailable:<detail>`).
An affected protocol impl for a type outside the project is a full run
(`unmapped_file:<impl file>`).

An ignored file affects no source, but a test that reads it from the repo
(its map `reads`) must still run: a change of only ignored files reads
the map (building it if missing) to find those tests, and no graph.

A selected test whose map entry is stale (its test file or a ref changed
since the map was built) or missing is a full run with exit status 2
(`test_map_unavailable:stale_entry:<test file>`): its references may be out
of date. A map built for the run is never stale; this guards prebuilt maps.

# `opts`

```elixir
@type opts() :: [
  root: Path.t(),
  config: MixAffected.Config.t(),
  test_files: [MixAffected.Graph.path()],
  graph_source: String.t(),
  graph: (-&gt; {:ok, MixAffected.Graph.t()} | {:error, MixAffected.Graph.error()}),
  test_map: (-&gt; {:ok, MixAffected.TestMap.t()} | {:error, String.t()})
]
```

# `defaults`

```elixir
@spec defaults(Path.t(), MixAffected.Config.t(), Path.t()) :: opts()
```

Real `run/2` options for the project at `root`: the graph from `mix xref`
(test env), the test map from `map_path`, built by a child
`mix affected.map` when the file is missing.

# `ensure_map`

```elixir
@spec ensure_map(Path.t(), Path.t()) ::
  {:ok, MixAffected.TestMap.t()} | {:error, String.t()}
```

Reads the map at `map_path`, building it there with a child
`mix affected.map` when it is missing or in a format this version does not
read (an older map lacks data selection relies on). The child's
`mix_affected: warning:` lines are passed on to stderr.

# `run`

```elixir
@spec run([String.t()], opts()) :: MixAffected.Result.t()
```

Runs a selection over `changed`. Options (all required; `defaults/3` builds
them for a real project):

  * `:root` - absolute project root
  * `:config` - `MixAffected.Config`
  * `:test_files` - every existing test file, root-relative
  * `:graph_source` - adapter name for the JSON `graph_source`
  * `:graph` - builds the graph, called at most once and only if a source changed
  * `:test_map` - reads or builds the test map, called at most once and
    only if anything is affected

# `source_name`

```elixir
@spec source_name(module()) :: String.t()
```

The JSON `graph_source` name of an adapter.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
