Packages

Use Elixir as a scripting language with Hex packages, anywhere on your system. No Mix project required!

Current section

Files

Jump to
teex lib pipeline install.ex
Raw

lib/pipeline/install.ex

defmodule Teex.Pipeline.Install do
@moduledoc false
alias Teex.Types.Library
alias Teex.Types.Workspace
alias Teex.Types.Error
alias Teex.Util.Messages
alias Teex.Util.Tar
def run(%Library{tarball: nil}, _) do
{:error, Error.build(type: :install, details: "Empty tarball passed into Install.run/2 pipeline")}
end
def run(%Library{} = lib, %Workspace{installed_libraries: current_libs} = target_workspace) do
if !File.dir?(target_workspace.path) do
{:error, Error.build(type: :workspace, details: "Workspace directory does not exist")}
else
with {:ok, tar_path} <- save_outer_tarball(lib),
{:ok, inner_tarball} <- extract_inner_tarball(tar_path),
{:ok, _lib_path} <- install_inner_tarball(target_workspace, lib, inner_tarball),
:ok <- install_and_compile(target_workspace, lib) do
lib = struct(lib, tarball: nil)
{:ok, struct(target_workspace, installed_libraries: [lib | current_libs])}
else
error -> error
end
end
end
defp save_outer_tarball(%Library{} = lib) do
temp_file = Path.join(System.tmp_dir!(), lib.name <> lib.version <> ".tar")
with {:ok, file_handle} <- File.open(temp_file, [:write]),
:ok <- IO.binwrite(file_handle, lib.tarball),
:ok <- File.close(file_handle) do
{:ok, temp_file}
else
_ -> {:error, Error.build(type: :install, details: "Failed to extract inner tarball from outter tarball")}
end
end
defp extract_inner_tarball(tar_location) do
Messages.outbox("Extracting inner tarball from outter tarball")
with {:ok, file_list} <- Tar.extract_tar_to_memory(tar_location),
{'contents.tar.gz', compressed_content} <- Enum.find(file_list, fn {file, _} -> file == 'contents.tar.gz' end) do
{:ok, compressed_content}
else
_ -> {:error, Error.build(type: :install, details: "Failed to extract inner tarball from outter tarball")}
end
end
def install_inner_tarball(%Workspace{} = workspace, %Library{} = lib, tar_data) do
lib_dir = Path.join(workspace.path, lib.name)
|> Path.join(lib.version)
file_path = Path.join(lib_dir, "contents.tar.gz")
with :ok <- File.mkdir_p(lib_dir),
{:ok, file_handle} <- File.open(file_path, [:write]),
:ok <- IO.binwrite(file_handle, tar_data),
:ok <- File.close(file_handle) do
Tar.extract_tar_to_dir(file_path, lib_dir)
else
err -> {:error, Error.build(type: :install, details: "Failed to install the inner tarball", data: err)}
end
end
defp install_and_compile(%Workspace{} = workspace, %Library{} = lib) do
Messages.wrench("Installing #{lib.name} @ #{lib.version} into workspace: #{workspace.name}")
lib_path = Path.join([workspace.path, lib.name, lib.version])
Messages.package("Fetching and compiling deps for #{lib.name} @ #{lib.version}")
System.cmd("mix", ["deps.get"], cd: lib_path, stderr_to_stdout: true)
System.cmd("mix", ["deps.compile"], cd: lib_path, stderr_to_stdout: true)
Messages.tools("Compiling #{lib.name} @ #{lib.version}")
System.cmd("mix", ["compile"], cd: lib_path, stderr_to_stdout: true)
:ok
end
end