use std::path::PathBuf;
use anyhow::{Context, Result};
use linera_base::command::{current_binary_parent, CommandExt};
use pathdiff::diff_paths;
use tokio::process::Command;
use crate::cli_wrappers::local_kubernetes_net::BuildMode;
pub enum Dockerfile {
Main,
Indexer,
Explorer,
}
impl Dockerfile {
pub fn path(&self) -> &'static str {
match self {
Dockerfile::Main => "docker/Dockerfile",
Dockerfile::Indexer => "docker/Dockerfile.indexer",
Dockerfile::Explorer => "docker/Dockerfile.explorer",
}
}
}
pub struct DockerImage {
name: String,
}
impl DockerImage {
pub fn name(&self) -> &String {
&self.name
}
pub async fn build(
name: String,
binaries: BuildArg,
github_root: PathBuf,
build_mode: BuildMode,
dual_store: bool,
dockerfile: Dockerfile,
) -> Result<Self> {
let docker_image = Self {
name: name.to_owned(),
};
let mut command = Command::new("docker");
command
.current_dir(github_root.clone())
.arg("build")
.args(["-f", dockerfile.path()]);
if let Dockerfile::Main = dockerfile {
let build_arg = match binaries {
BuildArg::Directory(bin_path) => {
let bin_path = diff_paths(bin_path, github_root)
.context("Getting relative path failed")?;
let bin_path_str = bin_path.to_str().context("Getting str failed")?;
format!("binaries={bin_path_str}")
}
BuildArg::ParentDirectory => {
let parent_path = current_binary_parent()
.expect("Fetching current binaries path should not fail");
let bin_path = diff_paths(parent_path, github_root)
.context("Getting relative path failed")?;
let bin_path_str = bin_path.to_str().context("Getting str failed")?;
format!("binaries={bin_path_str}")
}
BuildArg::Build => {
let arch = std::env::consts::ARCH;
let docker_arch = match arch {
"arm" => "aarch",
_ => arch,
};
format!("target={docker_arch}-unknown-linux-gnu")
}
};
command.args(["--build-arg", &build_arg]);
match build_mode {
BuildMode::Release => {}
BuildMode::Debug => {
command.args(["--build-arg", "build_folder=debug"]);
command.args(["--build-arg", "build_flag="]);
}
}
if dual_store {
command.args(["--build-arg", "build_features=rocksdb,scylladb,metrics"]);
}
#[cfg(not(with_testing))]
command
.args([
"--build-arg",
&format!(
"git_commit={}",
linera_version::VersionInfo::get()?.git_commit
),
])
.args([
"--build-arg",
&format!(
"build_date={}",
chrono::Utc::now().format("%a %b %d %T UTC %Y")
),
]);
}
command
.arg(".")
.args(["-t", &name])
.spawn_and_wait()
.await?;
Ok(docker_image)
}
}
#[derive(Clone)]
pub enum BuildArg {
Build,
ParentDirectory,
Directory(PathBuf),
}
impl From<Option<Option<PathBuf>>> for BuildArg {
fn from(arg: Option<Option<PathBuf>>) -> Self {
match arg {
None => BuildArg::Build,
Some(None) => BuildArg::ParentDirectory,
Some(Some(path)) => BuildArg::Directory(path),
}
}
}