assemble-core 0.2.0

The core crate of the assemble-rs package
Documentation
use assemble_core::file_collection::{FileCollection, FileSet};
use assemble_core::flow::output::SinglePathOutputTask;
use assemble_core::lazy_evaluation::ProviderExt;
use assemble_core::lazy_evaluation::{Prop, Provider};
use assemble_core::logging::{LoggingArgs, OutputType};
use assemble_core::prelude::TaskId;
use assemble_core::project::buildable::Buildable;
use assemble_core::project::error::ProjectResult;
use assemble_core::project::finder::TaskFinder;
use assemble_core::project::shared::SharedProject;
use assemble_core::task::initialize_task::InitializeTask;
use assemble_core::task::up_to_date::UpToDate;
use assemble_core::{BuildResult, Executable, Project, Task};
use assemble_macros::{CreateTask, TaskIO};
use log::LevelFilter;
use more_collection_macros::set;
use once_cell::sync::Lazy;
use std::collections::HashSet;
use std::path::{Path, PathBuf};

static PROJECT: Lazy<SharedProject> = Lazy::new(init_project);
static TEMP_FILE: &str = "temp_file.txt";
static TEMP_DIR_DEST: &str = "dest";

#[derive(Debug, CreateTask, TaskIO)]
struct TestCopy {
    from: Prop<FileSet>,
    into: Prop<PathBuf>,
}

impl SinglePathOutputTask for TestCopy {
    fn get_path(task: &Executable<Self>) -> PathBuf {
        task.into.get()
    }
}

impl UpToDate for TestCopy {}

impl InitializeTask for TestCopy {
    fn initialize(task: &mut Executable<Self>, _project: &Project) -> ProjectResult {
        task.depends_on(task.from.clone());
        Ok(())
    }
}

impl Task for TestCopy {
    fn task_action(_task: &mut Executable<Self>, _project: &Project) -> BuildResult {
        todo!()
    }
}

fn base_file(path: impl AsRef<Path>) -> PathBuf {
    if cfg!(windows) {
        PathBuf::from("C:\\").join(path)
    } else {
        PathBuf::from("/").join(path)
    }
}

fn init_project() -> SharedProject {
    let mut project = Project::temp("dependencies");

    let mut copy_file_handle = project.register_task::<TestCopy>("copyFile").unwrap();
    let mut copy_file_handle2 = project.register_task::<TestCopy>("copyFile2").unwrap();

    let mut configurations = project.configurations_mut();
    let mut config1 = configurations.create("config1").clone();
    config1.add_dependency(PathBuf::from(TEMP_FILE));

    let config2 = configurations
        .create_with("config2", |config| {
            config.add_dependency(copy_file_handle.clone())
        })
        .clone();

    drop(configurations);

    copy_file_handle
        .configure_with(|c, _p| {
            c.from.set_with(config1)?;
            c.into.set(TEMP_DIR_DEST)?;
            Ok(())
        })
        .unwrap();

    copy_file_handle2
        .configure_with(|c, _p| {
            c.from.set_with(config2)?;
            Ok(())
        })
        .unwrap();

    project
}
#[test]
fn tasks_transitive_task_dependencies_through_configurations() {
    LoggingArgs::init_root_logger_with(LevelFilter::Trace, OutputType::Basic);
    let project = &*PROJECT;
    let mut task = project.find_task("copyFile2").unwrap().clone();
    let dependencies = project
        .with(|p| -> Result<_, _> {
            println!("resolving task...");
            let built_by = task.resolve(p)?.built_by();
            println!("built_by = {:#?}", built_by);
            built_by.get_dependencies(p)
        })
        .unwrap();
    println!("dependencies: {:?}", dependencies);
    let finder = TaskFinder::new(project);
    assert_eq!(
        dependencies,
        set!(finder
            .find("copyFile")
            .ok()
            .flatten()
            .unwrap()
            .first()
            .cloned()
            .unwrap())
    )
}

#[test]
fn resolve_file_only_configuration() {
    let project = &*PROJECT;
    let config1 = project
        .configurations()
        .get("config1")
        .unwrap()
        .resolved()
        .unwrap();
    assert_eq!(config1.files(), HashSet::from_iter([base_file(TEMP_FILE)]));
}

#[test]
fn configuration_with_task_dependencies_resolves() {
    let project = &*PROJECT;
    let config2 = project.configurations().get("config2").cloned().unwrap();
    assert_eq!(
        config2.resolved().unwrap().files(),
        HashSet::from_iter([PathBuf::from(TEMP_DIR_DEST)])
    );
    let dependencies = project.with(|p| config2.get_dependencies(p)).unwrap();
    println!("dependencies: {:?}", dependencies);
    let finder = TaskFinder::new(project);
    assert_eq!(
        dependencies,
        set!(finder
            .find("copyFile")
            .ok()
            .flatten()
            .unwrap()
            .first()
            .cloned()
            .unwrap())
    )
}