-
Notifications
You must be signed in to change notification settings - Fork 0
/
compile.lib_elixir.ex
89 lines (68 loc) · 1.94 KB
/
compile.lib_elixir.ex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
defmodule Mix.Tasks.Compile.LibElixir do
@moduledoc """
A utility for generating namespaced core Elixir modules for any version.
"""
use Mix.Task.Compiler
alias LibElixir.Artifact
alias LibElixir.Namespace
require Logger
@impl true
def run(_args) do
manifest = get_manifest()
case required_lib_elixir(manifest) do
{:ok, {module, ref, targets}} ->
compile(module, ref, targets)
manifest
|> put_in([:libs, module], %{ref: ref, targets: targets})
|> write_manifest!()
:ok
_ ->
:noop
end
end
@impl true
def manifests do
[manifest_path()]
end
@impl true
def clean do
File.rm(manifest_path())
:ok
end
def compile(module, ref, targets) do
artifact = Artifact.prepare!(ref)
target_directory = Mix.Project.compile_path()
Namespace.transform!(targets, module, artifact.ebin_directory, target_directory)
:ok
end
defp manifest_path do
Path.join(Mix.Project.app_path(), ".lib_elixir")
end
defp get_manifest do
manifest_path()
|> File.read!()
|> :erlang.binary_to_term()
rescue
_ -> %{libs: %{}}
end
defp write_manifest!(manifest) do
File.write!(manifest_path(), :erlang.term_to_binary(manifest))
end
defp required_lib_elixir(manifest) do
with {:ok, config} <- Keyword.fetch(config(), :lib_elixir) do
Keyword.validate!(config, [:namespace, :ref, :modules])
module = config[:namespace] || raise ":lib_elixir config must have `:namespace`"
ref = config[:ref] || raise ":lib_elixir config must have `:ref`"
targets = config[:modules] || raise ":lib_elixir config must have `:modules`"
manifest_lib = Map.get(manifest.libs, module, %{ref: nil, targets: []})
if manifest_lib.ref == ref and targets -- manifest_lib.targets == [] do
:error
else
{:ok, {module, ref, targets}}
end
end
end
defp config do
Mix.Project.config()
end
end