use std::{collections::BTreeMap, path::PathBuf};
use serde::{Deserialize, Serialize};
mod async_master;
mod eval;
pub mod json;
mod remote_proto;
mod remote_worker;
mod run;
mod serde_config;
mod session;
mod state;
mod watch;
mod worker;
mod worker_config;
mod worker_process;
#[allow(clippy::all, warnings)]
mod worker_capnp {
include!(concat!(env!("OUT_DIR"), "/worker_capnp.rs"));
}
pub use session::Session;
pub const WORKER_ENV: &str = "EVIX_WORKER";
#[derive(Debug, Clone)]
pub enum Input {
Flake(String),
Expr(String),
File(PathBuf),
}
#[derive(Debug, Clone)]
pub enum AutoArg {
Expr(String),
Str(String),
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Config {
#[serde(with = "serde_config::input")]
pub input: Input,
#[serde(with = "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)]
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>,
}
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,
meta: false,
show_input_drvs: false,
override_inputs: Vec::new(),
nix_options: Vec::new(),
remotes: Vec::new(),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Remote {
#[serde(alias = "host")]
pub endpoint: String,
pub systems: Vec<String>,
pub workers: usize,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Derivation {
pub attr: String,
pub attr_path: Vec<String>,
pub name: String,
pub system: String,
pub drv_path: String,
pub outputs: BTreeMap<String, Option<String>>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub meta: Option<serde_json::Value>,
#[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
pub input_drvs: BTreeMap<String, serde_json::Value>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub constituents: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub gc_root_error: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EvalError {
pub attr: String,
pub attr_path: Vec<String>,
pub error: String,
pub fatal: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Diff {
pub added: Vec<Derivation>,
pub removed: Vec<Derivation>,
pub errors: Vec<EvalError>,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Filter {
pub systems: Option<Vec<String>>,
pub attr_prefix: Option<Vec<String>>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum Event {
Derivation(Derivation),
AttrSet {
attr: String,
attr_path: Vec<String>,
attrs: Vec<String>,
},
Error(EvalError),
}
impl Event {
pub fn attr(&self) -> &str {
match self {
Event::Derivation(d) => &d.attr,
Event::AttrSet { attr, .. } => attr,
Event::Error(e) => &e.attr,
}
}
pub fn attr_path(&self) -> &[String] {
match self {
Event::Derivation(d) => &d.attr_path,
Event::AttrSet { attr_path, .. } => attr_path,
Event::Error(e) => &e.attr_path,
}
}
}
pub fn run_worker() -> anyhow::Result<()> {
tokio::runtime::Builder::new_current_thread()
.enable_io()
.build()?
.block_on(worker::run())
}
pub async fn serve_remote_worker(addr: &str) -> anyhow::Result<()> {
remote_worker::serve(addr).await
}