Mutare.Config (mutare v0.1.0)

Copy Markdown View Source

Translate Mutare options from an optional .mutare.exs file and CLI flags.

CLI flags win over file config. The result is a raw keyword list that Mutare.Options.new/1 normalizes and validates into the Mutare.Options struct threaded through the rest of the pipeline. This module owns CLI syntax and precedence only; it does not resolve runtime option values.

The 1:1 passthrough flags (whose CLI name is a plain rename of an option key) are derived from Mutare.Options.Registry, so this module only spells out the exceptional flags it actually translates (see cli_switches/0 and the translations in merge/2).

Summary

Functions

The CLI switches this module owns: the exceptional/translated flags whose mapping is not a 1:1 passthrough (a repeatable accumulator, a renamed/derived key, or a --no- toggle handled in merge/2). The Mix task composes these with Mutare.Options.Registry.cli_switches/0 (the passthrough options) and its own project/inspect flags into OptionParser's strict switch list, so a flag's parse shape lives next to its translation.

Load .mutare.exs from root, or [] when it is absent.

Merge file_config with parsed CLI flags into an options keyword list for Mutare.Options.new/1. CLI flags win over file config: each set flag is translated to its option key and put over the file value; an unset flag leaves the file's value (or the option default) in place. For translated boolean flags, the negative form is a real override too: e.g. --no-full restores coverage-guided selection and --no-partition-db disables partitioning even when .mutare.exs enabled it.

Functions

cli_switches()

@spec cli_switches() :: keyword()

The CLI switches this module owns: the exceptional/translated flags whose mapping is not a 1:1 passthrough (a repeatable accumulator, a renamed/derived key, or a --no- toggle handled in merge/2). The Mix task composes these with Mutare.Options.Registry.cli_switches/0 (the passthrough options) and its own project/inspect flags into OptionParser's strict switch list, so a flag's parse shape lives next to its translation.

load(root)

@spec load(Path.t()) :: keyword()

Load .mutare.exs from root, or [] when it is absent.

merge(file_config, flags)

@spec merge(keyword(), keyword()) :: keyword()

Merge file_config with parsed CLI flags into an options keyword list for Mutare.Options.new/1. CLI flags win over file config: each set flag is translated to its option key and put over the file value; an unset flag leaves the file's value (or the option default) in place. For translated boolean flags, the negative form is a real override too: e.g. --no-full restores coverage-guided selection and --no-partition-db disables partitioning even when .mutare.exs enabled it.

The recognised flags and what they mean are documented for users in the Mix.Tasks.Mutare moduledoc — this is the translation layer, so it records only the mappings that aren't a 1:1 rename: a repeatable --only accumulates into :paths (each a directory or single .ex file, in order), --line FILE:LINE into :only_lines, --skip-lifting Module.fun/arity into :skip_lifting, --skip-call Module.fun/arity (or Module.fun for any arity, Module.* for a whole module) appends a {Module, :fun, arity, :skip} route to :call_routes (the one flag that extends the file value rather than replacing it, so a run can skip one more call without restating the file's routes), --full/--no-full and --per-file/--no-per-file resolve to :test_selection, and --partition-db/--no-partition-db/--partition-env resolve to :partition_env. A :mutators CLI value is translated from CSV into a list of names; Mutare.Options resolves those names, including the :builtins group token, through the mutator catalog.

iex> opts = Mutare.Config.merge([paths: ["lib"], min_score: 70], only: "lib/billing", full: true)
iex> {opts[:paths], opts[:min_score], opts[:test_selection]}
{["lib/billing"], 70, :full}

iex> Mutare.Config.merge([], report: "json:mutare.json")[:reporters]
[{:human, nil}, {:json, "mutare.json"}]