Current section
Files
Jump to
Current section
Files
lib/file.ex
defmodule ExLoader.File do
@moduledoc """
copy file to remote nodes.
"""
alias ExLoader.Adapters
@adapters %{
file: Adapters.File,
http: Adapters.Http
}
@prefix Atom.to_string(ExLoader.MixProject.project()[:app])
def valid_file?(src) do
adapter = get_adapter(src)
case adapter do
nil -> false
adapter -> apply(adapter, :valid?, [src])
end
end
def copy(remote_node, src) do
with {:ok, bin} <- read(src),
{:ok, dst} <- mkdir_p(remote_node, src),
{:ok, dst} <- write(remote_node, dst, bin) do
{:ok, dst}
else
err -> err
end
end
def uncompress(remote_node, tarball) do
parent = Path.dirname(tarball)
{_, status} =
:rpc.call(remote_node, System, :cmd, [
"tar",
["zxvf", tarball],
[cd: parent, stderr_to_stdout: true]
])
case status do
0 ->
:ok
_ ->
{:error, %{msg: "failed to uncompress the release tarball: #{tarball}", reason: :badfile}}
end
end
defp mkdir_p(remote_node, src) do
dst = "/tmp/#{@prefix}.#{Nanoid.generate()}/#{Path.basename(src)}"
result = :rpc.call(remote_node, File, :mkdir_p, [Path.dirname(dst)])
case result do
:ok ->
{:ok, dst}
{:error, reason} ->
{:error,
%{
msg:
"cannot copy file to target node due to dir creation failure for #{dst}. Reason: #{
inspect(reason)
}"
}}
end
end
defp write(remote_node, dst, bin) do
result = :rpc.call(remote_node, File, :write, [dst, bin])
case result do
:ok ->
{:ok, dst}
{:error, reason} ->
{:error,
%{msg: "cannot write to file #{dst}. Reason: #{inspect(reason)}", reason: reason}}
end
end
defp read(src) do
adapter = get_adapter(src)
case adapter do
nil -> {:error, %{msg: "not supported file #{src}", reason: :badfile}}
_ -> apply(adapter, :get_content, [src])
end
end
defp get_adapter(src) do
%URI{scheme: scheme} = URI.parse(src)
type =
case scheme do
nil -> :file
s when s in ["https", "http", "ftp"] -> :http
_ -> nil
end
Map.get(@adapters, type)
end
end