use crate::config::ConfigurationEntry;
use crate::execution::{progress::Progress, repository::JobRepository, Runner as _, Simple};
use crate::graph::{Builder, Graph};
use crate::job::JobId;
use futures_lite::{Stream, StreamExt};
use std::env;
#[cfg(feature = "main-blocking")]
pub fn main() -> Result<(), Error> {
futures_lite::future::block_on(main_async())
}
#[cfg(not(feature = "main-blocking"))]
pub fn main() -> Result<(), Error> {
tree()?;
eprintln!("The main-blocking feature is not enabled, cannot run jobs, then.");
std::process::exit(1)
}
pub async fn main_async() -> Result<(), Error> {
logging();
let mut graph = build()?;
{
let mut events = run(&mut graph);
while let Some((id, outcome)) = events.next().await {
println!("{id}: {outcome:?}");
}
}
log::info!("Graph:\n{graph}");
Ok(())
}
pub fn tree() -> Result<(), Error> {
logging();
let goals = goals();
let graph = build()?;
for (indent, job, conditions) in graph.tree(&goals) {
print!("{}", " ".repeat(indent));
println!("{job} ({conditions})");
}
log::info!("Graph:\n{graph}");
Ok(())
}
pub fn logging() {
#[cfg(feature = "pretty_env_logger")]
return pretty_env_logger::init();
#[cfg(feature = "env_logger")]
return env_logger::init();
}
pub fn goals() -> Vec<Box<str>> {
let goals = env::var("WILLDO_GOALS")
.unwrap_or_default()
.split(",")
.map(Into::<Box<str>>::into)
.filter(|goal| !goal.is_empty())
.collect::<Vec<Box<str>>>();
goals
}
pub fn config(
) -> impl IntoIterator<Item = Result<impl ConfigurationEntry, crate::config::LoadError>> {
crate::config::load(env::var("WILLDO_CONFIG").unwrap_or(".".into()))
}
pub fn builder() -> Result<Builder, Error> {
let config = config();
let mut builder = Graph::builder();
for entry in config {
entry?.configure(&mut builder)?;
}
Ok(builder)
}
pub fn build() -> Result<Graph, Error> {
let mut builder = builder()?;
#[cfg(feature = "subprocess")]
builder.configure_provider(
"subprocess",
crate::execution::commander::subprocess::provide,
);
let graph = builder.build()?;
Ok(graph)
}
pub fn run<'j, J: 'j + JobRepository + Send + Unpin>(
jobs: J,
) -> impl 'j + Stream<Item = (JobId, Progress)> {
let goals = goals();
Simple.run(jobs, &goals)
}
#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error("Configuration failed - {0}")]
Configuration(#[from] crate::config::LoadError),
#[error("Task graph build failed - {0}")]
Graph(#[from] crate::graph::BuildError),
}