defmodule Mix.Tasks.Arch.Apps.Xref do @moduledoc """ Mix Task to generate a dependency graph for the applications within an umbrella. Usage: mix arch.apps.xref [options] The following options are accepted: * `--format` - Can be one of `dot` or `png` * `--out` - Output filename """ @shortdoc "Generates a dependency graph of applications" require Logger require EEx use Mix.Task @supported_formats ["png", "dot", "mermaid"] @impl Mix.Task def run(argv) do _run(argv, Mix.Project.umbrella?()) end defp _run(_, false) do IO.puts(:stderr, "This task works only with umbrella projects!") end defp _run(argv, _) do case parse_args(argv) do {:ok, [format: format, out: out_file]} -> Archeometer.Analysis.Apps.Xref.gen_graph(format) |> write(out_file) IO.puts(:stderr, "Graph ready at: '#{out_file}'") {:error, error} -> IO.puts(:stderr, "Error #{inspect(error)}") print_help() end end defp parse_args(argv) do {opts, _, invalid_switches} = OptionParser.parse( argv, # --db is currently supported, but NOT USED strict: [format: :string, out: :string, db: :string] ) case invalid_switches do [] -> format = Keyword.get(opts, :format, "dot") out_fname = Keyword.get(opts, :out, "console") case validate_options(format, out_fname) do :ok -> {:ok, [ format: format, out: out_fname ]} {:error, error} -> {:error, error} end _ -> {:error, :wrong_arguments} end end defp validate_options(format, out_fname) do cond do not (format in @supported_formats) -> {:error, :unsuppored_output_format} format == "png" and out_fname == "console" -> {:error, :png_not_writable_to_console} true -> :ok end end defp print_help() do IO.puts(:stderr, "Usage: mix arch.apps.xref [opts]") IO.puts( :stderr, "opts: --format (dot, png), --out out_fname" ) end defp write(content, "console") do IO.puts(content) end defp write(content, out_fname) do File.write!(out_fname, content) end end