defmodule Mix.Tasks.Lcov do
@moduledoc "Generates lcov test coverage files for the application"
@shortdoc "Generates lcov files"
@preferred_cli_env :test
use Mix.Task
alias LcovEx.MixFileHelper
require Logger
@doc """
Generates the `lcov.info` file.
"""
@impl Mix.Task
def run(args) do
{opts, files} = OptionParser.parse!(args, strict: [quiet: :boolean, output: :string])
path = Enum.at(files, 0) || File.cwd!()
affected_files =
case Mix.Project.apps_paths() do
nil ->
[Path.join([path, "mix.exs"])]
apps_paths ->
for {_app, app_path} <- apps_paths, do: Path.join([path, app_path, "mix.exs"])
end
|> Enum.map(fn path -> String.replace(path, "//", "/") end)
Enum.each(affected_files, fn mix_path -> MixFileHelper.backup(mix_path) end)
output = opts[:output] || "cover"
file_path = "#{output}/lcov.info"
File.mkdir_p!(output)
File.rm(file_path)
try do
config = [test_coverage: [tool: LcovEx, output: output]]
Enum.each(affected_files, fn mix_path ->
MixFileHelper.update_project_config(mix_path, config)
end)
task_opts =
if opts[:quiet] do
[cd: path]
else
[cd: path, into: IO.stream(:stdio, :line)]
end
System.cmd("mix", ["test", "--cover"], task_opts)
unless opts[:quiet] do
IO.puts("\nCoverage file successfully created at #{file_path}")
end
after
Enum.each(affected_files, fn mix_path -> MixFileHelper.recover(mix_path) end)
end
end
end