use std::path::PathBuf;
pub use evix_protocol::{AutoArg, Input, Remote};
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Config {
#[serde(with = "evix_protocol::serde_config::input")]
pub input: Input,
#[serde(with = "evix_protocol::serde_config::auto_args")]
pub auto_args: Vec<(String, AutoArg)>,
#[serde(default)]
pub force_recurse: bool,
pub gc_roots_dir: Option<PathBuf>,
pub workers: usize,
pub max_memory_size: usize,
#[serde(default = "default_item_timeout_seconds")]
pub item_timeout_seconds: u64,
#[serde(default)]
pub meta: bool,
#[serde(default)]
pub show_input_drvs: bool,
#[serde(default)]
pub override_inputs: Vec<(String, String)>,
#[serde(default)]
pub nix_options: Vec<(String, String)>,
#[serde(default)]
pub remotes: Vec<Remote>,
#[serde(skip)]
pub worker_exe: Option<PathBuf>,
}
impl Default for Config {
fn default() -> Self {
Self {
input: Input::Expr("{}".into()),
auto_args: Vec::new(),
force_recurse: false,
gc_roots_dir: None,
workers: 1,
max_memory_size: 4096,
item_timeout_seconds: default_item_timeout_seconds(),
meta: false,
show_input_drvs: false,
override_inputs: Vec::new(),
nix_options: Vec::new(),
remotes: Vec::new(),
worker_exe: None,
}
}
}
impl Config {
#[must_use]
pub fn expr(expr: impl Into<String>) -> Self {
Self {
input: Input::Expr(expr.into()),
..Self::default()
}
}
#[must_use]
pub fn file(path: impl Into<PathBuf>) -> Self {
Self {
input: Input::File(path.into()),
..Self::default()
}
}
#[must_use]
pub fn flake(reference: impl Into<String>) -> Self {
Self {
input: Input::Flake(reference.into()),
..Self::default()
}
}
#[must_use = "builders do nothing unless consumed with build"]
pub fn builder(self) -> ConfigBuilder {
ConfigBuilder { config: self }
}
}
#[derive(Debug, Clone)]
pub struct ConfigBuilder {
config: Config,
}
impl ConfigBuilder {
#[must_use = "builders do nothing unless consumed with build"]
pub fn expr(expr: impl Into<String>) -> Self {
Config::expr(expr).builder()
}
#[must_use = "builders do nothing unless consumed with build"]
pub fn file(path: impl Into<PathBuf>) -> Self {
Config::file(path).builder()
}
#[must_use = "builders do nothing unless consumed with build"]
pub fn flake(reference: impl Into<String>) -> Self {
Config::flake(reference).builder()
}
#[must_use = "builder methods return a modified builder"]
pub fn force_recurse(mut self, enabled: bool) -> Self {
self.config.force_recurse = enabled;
self
}
#[must_use = "builder methods return a modified builder"]
pub fn gc_roots_dir(mut self, path: impl Into<PathBuf>) -> Self {
self.config.gc_roots_dir = Some(path.into());
self
}
#[must_use = "builder methods return a modified builder"]
pub fn workers(mut self, workers: usize) -> Self {
self.config.workers = workers;
self
}
#[must_use = "builder methods return a modified builder"]
pub fn max_memory_size(mut self, size: usize) -> Self {
self.config.max_memory_size = size;
self
}
#[must_use = "builder methods return a modified builder"]
pub fn item_timeout_seconds(mut self, seconds: u64) -> Self {
self.config.item_timeout_seconds = seconds;
self
}
#[must_use = "builder methods return a modified builder"]
pub fn meta(mut self, enabled: bool) -> Self {
self.config.meta = enabled;
self
}
#[must_use = "builder methods return a modified builder"]
pub fn show_input_drvs(mut self, enabled: bool) -> Self {
self.config.show_input_drvs = enabled;
self
}
#[must_use = "builder methods return a modified builder"]
pub fn auto_arg_expr(
mut self,
name: impl Into<String>,
value: impl Into<String>,
) -> Self {
self
.config
.auto_args
.push((name.into(), AutoArg::Expr(value.into())));
self
}
#[must_use = "builder methods return a modified builder"]
pub fn auto_arg_str(
mut self,
name: impl Into<String>,
value: impl Into<String>,
) -> Self {
self
.config
.auto_args
.push((name.into(), AutoArg::Str(value.into())));
self
}
#[must_use = "builder methods return a modified builder"]
pub fn override_input(
mut self,
name: impl Into<String>,
reference: impl Into<String>,
) -> Self {
self
.config
.override_inputs
.push((name.into(), reference.into()));
self
}
#[must_use = "builder methods return a modified builder"]
pub fn nix_option(
mut self,
key: impl Into<String>,
value: impl Into<String>,
) -> Self {
self.config.nix_options.push((key.into(), value.into()));
self
}
#[must_use = "builder methods return a modified builder"]
pub fn remote(mut self, remote: Remote) -> Self {
self.config.remotes.push(remote);
self
}
#[must_use = "builder methods return a modified builder"]
pub fn worker_exe(mut self, path: impl Into<PathBuf>) -> Self {
self.config.worker_exe = Some(path.into());
self
}
#[must_use]
pub fn build(self) -> Config {
self.config
}
}
impl From<evix_protocol::Config> for Config {
fn from(config: evix_protocol::Config) -> Self {
Self {
input: config.input,
auto_args: config.auto_args,
force_recurse: config.force_recurse,
gc_roots_dir: config.gc_roots_dir,
workers: config.workers,
max_memory_size: config.max_memory_size,
item_timeout_seconds: config.item_timeout_seconds,
meta: config.meta,
show_input_drvs: config.show_input_drvs,
override_inputs: config.override_inputs,
nix_options: config.nix_options,
remotes: config.remotes,
worker_exe: None,
}
}
}
impl From<Config> for evix_protocol::Config {
fn from(config: Config) -> Self {
(&config).into()
}
}
impl From<&Config> for evix_protocol::Config {
fn from(config: &Config) -> Self {
Self {
input: config.input.clone(),
auto_args: config.auto_args.clone(),
force_recurse: config.force_recurse,
gc_roots_dir: config.gc_roots_dir.clone(),
workers: config.workers,
max_memory_size: config.max_memory_size,
item_timeout_seconds: config.item_timeout_seconds,
meta: config.meta,
show_input_drvs: config.show_input_drvs,
override_inputs: config.override_inputs.clone(),
nix_options: config.nix_options.clone(),
remotes: config.remotes.clone(),
}
}
}
fn default_item_timeout_seconds() -> u64 {
evix_protocol::DEFAULT_ITEM_TIMEOUT_SECONDS
}