Skip to content

Commit

Permalink
Generate individual checksum file for each target (#84)
Browse files Browse the repository at this point in the history
  • Loading branch information
cocoa-xu committed Mar 24, 2024
1 parent e41e23c commit 22a5511
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 27 deletions.
24 changes: 22 additions & 2 deletions lib/elixir_make/artefact.ex
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,33 @@ defmodule ElixirMake.Artefact do
cache_dir
end

@doc """
Returns the checksum algorithm
"""
def checksum_algo do
@checksum_algo
end

@doc """
Computes the checksum and artefact for the given contents.
"""
def checksum(basename, contents) do
hash = :crypto.hash(@checksum_algo, contents)
hash = :crypto.hash(checksum_algo(), contents)
checksum = Base.encode16(hash, case: :lower)
%Artefact{basename: basename, checksum: checksum, checksum_algo: @checksum_algo}
%Artefact{basename: basename, checksum: checksum, checksum_algo: checksum_algo()}
end

@doc """
Writes checksum for the target to disk.
"""
def write_checksum_for_target!(%Artefact{
basename: basename,
checksum: checksum,
checksum_algo: checksum_algo
}) do
cache_dir = Artefact.cache_dir()
file = Path.join(cache_dir, "#{basename}.#{Atom.to_string(checksum_algo)}")
File.write!(file, [checksum, " ", basename, "\n"])
end

@doc """
Expand Down
74 changes: 49 additions & 25 deletions lib/mix/tasks/elixir_make.checksum.ex
Original file line number Diff line number Diff line change
Expand Up @@ -103,38 +103,62 @@ defmodule Mix.Tasks.ElixirMake.Checksum do
tasks =
Task.async_stream(
urls,
fn {{_target, _nif_version}, url} -> {url, Artefact.download(url)} end,
fn {{_target, _nif_version}, url} ->
checksum_algo = Artefact.checksum_algo()
checksum_file_url = "#{url}.#{Atom.to_string(checksum_algo)}"
artifact_checksum = Artefact.download(checksum_file_url)

with {:ok, body} <- artifact_checksum,
[checksum, basename] <- String.split(body, " ", trim: true) do
{:checksum, url,
%Artefact{
basename: String.trim(basename),
checksum: checksum,
checksum_algo: checksum_algo
}}
else
_ -> {:download, url, Artefact.download(url)}
end
end,
timeout: :infinity,
ordered: false
)

cache_dir = Artefact.cache_dir()

Enum.flat_map(tasks, fn {:ok, {url, download}} ->
case download do
{:ok, body} ->
basename = basename_from_url(url)
path = Path.join(cache_dir, basename)
File.write!(path, body)
artefact = Artefact.checksum(basename, body)

Mix.shell().info(
"NIF cached at #{path} with checksum #{artefact.checksum} (#{artefact.checksum_algo})"
)

[artefact]

result ->
if ignore_unavailable? do
msg = "Skipped unavailable NIF artifact. Reason: #{inspect(result)}"
Mix.shell().info(msg)
else
msg = "Could not finish the download of NIF artifacts. Reason: #{inspect(result)}"
Mix.shell().error(msg)
end
Enum.flat_map(tasks, fn
{:ok, {:checksum, _url, artefact}} ->
Mix.shell().info(
"NIF checksum file with checksum #{artefact.checksum} (#{artefact.checksum_algo})"
)

[]
end
[artefact]

{:ok, {:download, url, download}} ->
case download do
{:ok, body} ->
basename = basename_from_url(url)
path = Path.join(cache_dir, basename)
File.write!(path, body)
artefact = Artefact.checksum(basename, body)

Mix.shell().info(
"NIF cached at #{path} with checksum #{artefact.checksum} (#{artefact.checksum_algo})"
)

[artefact]

result ->
if ignore_unavailable? do
msg = "Skipped unavailable NIF artifact. Reason: #{inspect(result)}"
Mix.shell().info(msg)
else
msg = "Could not finish the download of NIF artifacts. Reason: #{inspect(result)}"
Mix.shell().error(msg)
end

[]
end
end)
end

Expand Down
2 changes: 2 additions & 0 deletions lib/mix/tasks/elixir_make.precompile.ex
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ defmodule Mix.Tasks.ElixirMake.Precompile do
precompiler.post_precompile_target(target)
end

Artefact.write_checksum_for_target!(precompiled_artefacts)

precompiled_artefacts

{:error, msg} ->
Expand Down

0 comments on commit 22a5511

Please sign in to comment.