Current section

Files

Jump to
mix_audit lib mix_audit project.ex
Raw

lib/mix_audit/project.ex

defmodule MixAudit.Project do
def dependencies(path) do
Enum.flat_map(lockfiles(path), &map_lockfile_to_dependencies/1)
end
defp lockfiles(path) do
Path.wildcard(Path.join(path, "mix.lock")) ++ Path.wildcard(Path.join(path, "apps/**/mix.lock"))
end
defp map_lockfile_to_dependencies(lockfile) do
lockfile
|> read_lockfile()
|> Map.values()
|> Enum.map(&map_dependency(&1, lockfile))
|> Enum.reject(&is_nil/1)
end
defp read_lockfile(lockfile) do
opts = [file: lockfile, warn_on_unnecessary_quotes: false]
with {:ok, contents} <- File.read(lockfile),
assert_no_merge_conflicts_in_lockfile(lockfile, contents),
{:ok, quoted} <- Code.string_to_quoted(contents, opts),
{%{} = lock, _} <- Code.eval_quoted(quoted, [], opts) do
lock
else
_ -> %{}
end
end
defp map_dependency({:hex, package, version, _, _, _, _}, lockfile) do
do_map_dependency(package, version, lockfile)
end
defp map_dependency({:hex, package, version, _, _, _, _, _}, lockfile) do
do_map_dependency(package, version, lockfile)
end
defp map_dependency(_, _), do: nil
defp do_map_dependency(package, version, lockfile) do
%MixAudit.Dependency{package: to_string(package), version: version, lockfile: lockfile}
end
defp assert_no_merge_conflicts_in_lockfile(lockfile, info) do
if String.contains?(info, ~w(<<<<<<< ======= >>>>>>>)) do
Mix.raise("Your #{lockfile} contains merge conflicts. Please resolve the conflicts and run the command again")
end
end
end