defmodule Mix.Tasks.Lcov do @moduledoc "Generates lcov test coverage files for the application" @shortdoc "Generates lcov files" use Mix.Task require Logger @doc """ Generates the `lcov.info` file. """ @impl Mix.Task def run(args) do {opts, files} = OptionParser.parse!(args, strict: [quiet: :boolean, keep: :boolean, output: :string]) if opts[:quiet], do: Mix.shell(Mix.Shell.Quiet) path = Enum.at(files, 0) || File.cwd!() # Setup folder, reset file output = opts[:output] || "cover" file_path = "#{output}/lcov.info" File.mkdir_p!(output) File.rm(file_path) # Actually run tests and coverage args = Enum.join(args, " ") Mix.shell().cmd( "mix lcov.run #{args}", cd: path, env: [{"MIX_ENV", "test"}] ) # Umbrella projects support if Mix.Project.umbrella?() do for {app, path} <- Mix.Project.apps_paths() do app_lcov_path = Path.join(path, file_path) app_lcov = app_lcov_path |> File.read!() |> String.replace("SF:", "SF:#{path}/") File.write!(file_path, app_lcov, [:append]) if opts[:keep] do log_info("Coverage file for #{app} created at #{app_lcov_path}", opts) else File.rm!(app_lcov_path) end end log_info("\nCoverage file for umbrella created at #{file_path}", opts) end :ok end defp log_info(msg, opts) do unless Keyword.get(opts, :quiet, false) do Mix.shell().info(msg) end end end