check-elixir-deps-discrepancies.exs 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. #!/usr/bin/env elixir
  2. # ensure we have a fresh rebar.lock
  3. case File.stat("rebar.lock") do
  4. {:ok, _} ->
  5. File.rm!("rebar.lock")
  6. _ ->
  7. :ok
  8. end
  9. {_, 0} =
  10. File.cwd!()
  11. |> Path.join("rebar3")
  12. |> System.cmd(["tree"], into: IO.stream())
  13. {:ok, props} = :file.consult("rebar.lock")
  14. {[{_, rebar_deps}], [props]} = Enum.split_with(props, &is_tuple/1)
  15. # dpendencies declared as package versions have a "secondary index"
  16. pkg_idx =
  17. props
  18. |> Keyword.fetch!(:pkg_hash)
  19. |> Map.new()
  20. rebar_deps =
  21. Map.new(rebar_deps, fn {name, ref, _} ->
  22. ref =
  23. case ref do
  24. {:pkg, _, _} ->
  25. pkg_idx
  26. |> Map.fetch!(name)
  27. |> String.downcase()
  28. {:git, _, {:ref, ref}} ->
  29. to_string(ref)
  30. {:git_subdir, _, {:ref, ref}, _} ->
  31. to_string(ref)
  32. end
  33. {name, ref}
  34. end)
  35. {mix_deps, []} = Code.eval_file("mix.lock")
  36. mix_deps =
  37. Map.new(mix_deps, fn {name, ref} ->
  38. ref =
  39. case ref do
  40. {:git, _, ref, _} ->
  41. ref
  42. {:hex, _, _, ref, _, _, _, _} ->
  43. ref
  44. end
  45. {to_string(name), ref}
  46. end)
  47. diffs =
  48. Enum.reduce(rebar_deps, %{}, fn {name, rebar_ref}, acc ->
  49. mix_ref = mix_deps[name]
  50. cond do
  51. mix_ref && mix_ref != rebar_ref ->
  52. Map.put(acc, name, {rebar_ref, mix_ref})
  53. is_nil(mix_ref) ->
  54. Map.put(acc, name, {rebar_ref, nil})
  55. :otherwise ->
  56. acc
  57. end
  58. end)
  59. if diffs == %{} do
  60. IO.puts(
  61. IO.ANSI.green() <>
  62. "* Mix and Rebar3 dependencies OK!" <>
  63. IO.ANSI.reset()
  64. )
  65. System.halt(0)
  66. else
  67. IO.puts(
  68. IO.ANSI.red() <>
  69. "* Discrepancies between Elixir and Rebar3 dependencies found!" <>
  70. IO.ANSI.reset()
  71. )
  72. Enum.each(diffs, fn {name, {rebar_ref, mix_ref}} ->
  73. IO.puts(
  74. IO.ANSI.red() <>
  75. " * #{name}\n" <>
  76. " * Rebar3 ref: #{rebar_ref}\n" <>
  77. " * Mix ref: #{mix_ref}\n" <>
  78. IO.ANSI.reset()
  79. )
  80. end)
  81. IO.puts(
  82. IO.ANSI.red() <>
  83. "Update `mix.exs` to match Rebar3's references (use `overwrite: true` if necessary) " <>
  84. "and/or run `mix deps.get` to update and try again" <>
  85. IO.ANSI.reset()
  86. )
  87. System.halt(1)
  88. end