From 71f96f8734adc73c0651050bd9f0e20ff52c61a8 Mon Sep 17 00:00:00 2001
From: Unnawut Leepaisalsuwanna <unnawut@unnawut.com>
Date: Sat, 19 Jan 2019 01:59:02 +0700
Subject: [PATCH] Rely on hex_metadata.config instead of mix

---
 README.md                                     |  2 +-
 lib/licensir/guesser.ex                       | 12 ++++----
 lib/licensir/license.ex                       |  2 ++
 lib/licensir/scanner.ex                       | 30 +++++++++++++++----
 mix.exs                                       |  2 +-
 .../dep_license_undefined/hex_metadata.config |  0
 .../deps/dep_one_license/hex_metadata.config  |  1 +
 .../deps/dep_two_licenses/hex_metadata.config |  1 +
 .../hex_metadata.config                       |  1 +
 test/licensir/guesser_test.exs                | 20 ++++++-------
 10 files changed, 47 insertions(+), 24 deletions(-)
 create mode 100644 test/fixtures/deps/dep_license_undefined/hex_metadata.config
 create mode 100644 test/fixtures/deps/dep_one_license/hex_metadata.config
 create mode 100644 test/fixtures/deps/dep_two_licenses/hex_metadata.config
 create mode 100644 test/fixtures/deps/dep_two_variants_same_license/hex_metadata.config

diff --git a/README.md b/README.md
index 0ad8ed7..d92e53e 100644
--- a/README.md
+++ b/README.md
@@ -9,7 +9,7 @@ The package can be installed by adding `licensir` to your list of dependencies i
 ```elixir
 def deps do
   [
-    {:licensir, "~> 0.3.0", only: :dev, runtime: false}
+    {:licensir, "~> 0.4.0", only: :dev, runtime: false}
   ]
 end
 ```
diff --git a/lib/licensir/guesser.ex b/lib/licensir/guesser.ex
index fa76987..d6ad374 100644
--- a/lib/licensir/guesser.ex
+++ b/lib/licensir/guesser.ex
@@ -10,19 +10,19 @@ defmodule Licensir.Guesser do
   def guess(licenses) when is_list(licenses), do: Enum.map(licenses, &guess/1)
 
   def guess(%License{} = license) do
-    mix_licenses = NamingVariants.normalize(license.mix)
+    hex_metadata_licenses = NamingVariants.normalize(license.hex_metadata)
     file_licenses = NamingVariants.normalize(license.file)
 
-    conclusion = guess(mix_licenses, file_licenses)
+    conclusion = guess(hex_metadata_licenses, file_licenses)
     Map.put(license, :license, conclusion)
   end
 
   defp guess(nil, nil), do: "Undefined"
   defp guess(nil, file), do: file
-  defp guess(mix, nil) when length(mix) > 0, do: Enum.join(mix, ", ")
-  defp guess(mix, file) when length(mix) == 1 and hd(mix) == file, do: file
+  defp guess(hex, nil) when length(hex) > 0, do: Enum.join(hex, ", ")
+  defp guess(hex, file) when length(hex) == 1 and hd(hex) == file, do: file
 
-  defp guess(mix, file) do
-    "Unsure (found: " <> Enum.join(mix, ", ") <> ", " <> file <> ")"
+  defp guess(hex, file) do
+    "Unsure (found: " <> Enum.join(hex, ", ") <> ", " <> file <> ")"
   end
 end
diff --git a/lib/licensir/license.ex b/lib/licensir/license.ex
index bbe5ede..b2dba3d 100644
--- a/lib/licensir/license.ex
+++ b/lib/licensir/license.ex
@@ -21,6 +21,7 @@ defmodule Licensir.License do
             license: nil,
             certainty: 0.0,
             mix: nil,
+            hex_metadata: nil,
             file: nil
 
   @type t :: %__MODULE__{
@@ -31,6 +32,7 @@ defmodule Licensir.License do
           license: String.t() | nil,
           certainty: float(),
           mix: list(String.t()) | nil,
+          hex_metadata: list(String.t()) | nil,
           file: String.t() | nil
         }
 end
diff --git a/lib/licensir/scanner.ex b/lib/licensir/scanner.ex
index e5d01c7..c710018 100644
--- a/lib/licensir/scanner.ex
+++ b/lib/licensir/scanner.ex
@@ -26,7 +26,7 @@ defmodule Licensir.Scanner do
 
     deps()
     |> to_struct()
-    |> search_mix()
+    |> search_hex_metadata()
     |> search_file()
     |> Guesser.guess()
   end
@@ -48,18 +48,36 @@ defmodule Licensir.Scanner do
   defp get_version(%Mix.Dep{status: {:ok, version}}), do: version
   defp get_version(_), do: nil
 
-  defp search_mix(licenses) when is_list(licenses), do: Enum.map(licenses, &search_mix/1)
+  #
+  # Search in hex_metadata.config
+  #
 
-  defp search_mix(%License{} = license) do
-    Map.put(license, :mix, search_mix(license.dep))
+  defp search_hex_metadata(licenses) when is_list(licenses), do: Enum.map(licenses, &search_hex_metadata/1)
+
+  defp search_hex_metadata(%License{} = license) do
+    Map.put(license, :hex_metadata, search_hex_metadata(license.dep))
   end
 
-  defp search_mix(%Mix.Dep{} = dep) do
+  defp search_hex_metadata(%Mix.Dep{} = dep) do
     Mix.Dep.in_dependency(dep, fn _ ->
-      get_in(Mix.Project.config(), [:package, :licenses])
+      "hex_metadata.config"
+      |> :file.consult()
+      |> case do
+        {:ok, metadata} -> metadata
+        {:error, _} -> []
+      end
+      |> List.keyfind("licenses", 0)
+      |> case do
+        {_, licenses} -> licenses
+        _ -> nil
+      end
     end)
   end
 
+  #
+  # Search in LICENSE file
+  #
+
   defp search_file(licenses) when is_list(licenses), do: Enum.map(licenses, &search_file/1)
 
   defp search_file(%License{} = license) do
diff --git a/mix.exs b/mix.exs
index 6b2d6bd..12a11de 100644
--- a/mix.exs
+++ b/mix.exs
@@ -4,7 +4,7 @@ defmodule Licensir.Mixfile do
   def project do
     [
       app: :licensir,
-      version: "0.3.0",
+      version: "0.4.0",
       elixir: "~> 1.5",
       elixirc_paths: elixirc_paths(Mix.env()),
       escript: [main_module: Licensir.Licenses],
diff --git a/test/fixtures/deps/dep_license_undefined/hex_metadata.config b/test/fixtures/deps/dep_license_undefined/hex_metadata.config
new file mode 100644
index 0000000..e69de29
diff --git a/test/fixtures/deps/dep_one_license/hex_metadata.config b/test/fixtures/deps/dep_one_license/hex_metadata.config
new file mode 100644
index 0000000..fedfc72
--- /dev/null
+++ b/test/fixtures/deps/dep_one_license/hex_metadata.config
@@ -0,0 +1 @@
+{<<"licenses">>,[<<"License One">>]}.
diff --git a/test/fixtures/deps/dep_two_licenses/hex_metadata.config b/test/fixtures/deps/dep_two_licenses/hex_metadata.config
new file mode 100644
index 0000000..80eecd2
--- /dev/null
+++ b/test/fixtures/deps/dep_two_licenses/hex_metadata.config
@@ -0,0 +1 @@
+{<<"licenses">>,[<<"License Two">>, <<"License Three">>]}.
diff --git a/test/fixtures/deps/dep_two_variants_same_license/hex_metadata.config b/test/fixtures/deps/dep_two_variants_same_license/hex_metadata.config
new file mode 100644
index 0000000..e9476a6
--- /dev/null
+++ b/test/fixtures/deps/dep_two_variants_same_license/hex_metadata.config
@@ -0,0 +1 @@
+{<<"licenses">>,[<<"Apache 2">>, <<"Apache v2.0">>]}.
diff --git a/test/licensir/guesser_test.exs b/test/licensir/guesser_test.exs
index 7c87056..4bdd49c 100644
--- a/test/licensir/guesser_test.exs
+++ b/test/licensir/guesser_test.exs
@@ -3,9 +3,9 @@ defmodule Licensir.GuesserTest do
   alias Licensir.{Guesser, License}
 
   describe "Guesser.guess/1" do
-    test "returns the license in mix" do
+    test "returns the license in hex_metadata" do
       license = %License{
-        mix: ["License in Mix"],
+        hex_metadata: ["License in Mix"],
         file: nil
       }
 
@@ -14,34 +14,34 @@ defmodule Licensir.GuesserTest do
 
     test "returns the license in file" do
       license = %License{
-        mix: nil,
+        hex_metadata: nil,
         file: "License in file"
       }
 
       assert Guesser.guess(license).license == "License in file"
     end
 
-    test "returns the license if the license in mix and file are equal" do
+    test "returns the license if the license in hex_metadata and file are equal" do
       license = %License{
-        mix: ["Same License"],
+        hex_metadata: ["Same License"],
         file: "Same License"
       }
 
       assert Guesser.guess(license).license == "Same License"
     end
 
-    test "returns unsure if the license in mix and file are not the same" do
+    test "returns unsure if the license in hex_metadata and file are not the same" do
       license = %License{
-        mix: ["License One"],
+        hex_metadata: ["License One"],
         file: "License Two"
       }
 
       assert Guesser.guess(license).license == "Unsure (found: License One, License Two)"
     end
 
-    test "returns unsure if there are multiple licenses in mix and also one definted in file" do
+    test "returns unsure if there are multiple licenses in hex_metadata and also one definted in file" do
       license = %License{
-        mix: ["License One", "License Two"],
+        hex_metadata: ["License One", "License Two"],
         file: "License Three"
       }
 
@@ -51,7 +51,7 @@ defmodule Licensir.GuesserTest do
 
     test "returns Undefined if no license data is found" do
       license = %License{
-        mix: nil,
+        hex_metadata: nil,
         file: nil
       }