use std::{
path::PathBuf,
sync::{Arc, Mutex},
};
use fartdown::parser;
use fartdown::types::{LocationMap, URI};
use walkdir::WalkDir;
use super::{
graph::OpGraph,
op::{OpId, Operation},
types::{AppError, ArtifactMap, ErrorPathCtx},
utils::{is_file, is_visible},
};
use crate::cli::{artifact::Artifact, command::Command, utils::into_uri_path_tuple};
pub async fn index(
paths: Vec<PathBuf>,
locations: Arc<Mutex<LocationMap>>,
) -> Result<bool, AppError> {
let mut locations = locations.lock().expect("poisoned lock");
for path in paths {
let walker = WalkDir::new(path)
.into_iter()
.filter_entry(is_visible)
.filter_map(Result::ok)
.filter(is_file);
for entry in walker {
locations.insert(
entry.path().display().to_string(),
entry.path().to_path_buf(),
);
}
}
Ok(false)
}
pub async fn gather(op: Operation, operations: Arc<Mutex<OpGraph>>) -> Result<bool, AppError> {
let Operation::Gather { cmd, paths, splits: _ } = &op else {
panic!()
};
let mut graph = operations.lock().expect("poisoned lock");
for path in paths {
let walker = WalkDir::new(path)
.into_iter()
.filter_entry(is_visible)
.filter_map(Result::ok)
.filter(is_file)
.map(into_uri_path_tuple);
for (id, path) in walker {
let id: Arc<str> = Arc::from(id.as_ref());
match cmd {
Command::Load { .. } => {
if graph.get(&OpId::load(id.clone())).is_none() {
graph.insert_node_chain([Operation::Load { id, path }, Operation::Finish]);
} else {
}
}
Command::Build { .. } => graph.insert_node_chain([
Operation::Load { id: id.clone(), path },
Operation::Parse { id: id.clone() },
Operation::Finish,
]),
}
}
}
Ok(false)
}
pub async fn load(op: Operation, artifacts: Arc<Mutex<ArtifactMap>>) -> Result<bool, AppError> {
let Operation::Load { path, .. } = &op else {
unreachable!()
};
let artifact = match tokio::fs::read_to_string(path).await {
Ok(contents) => Artifact::String(contents),
Err(_) => Artifact::Binary(std::fs::read(path).with_ctx(path)?),
};
let mut artifacts = artifacts.lock().expect("poisoned lock");
artifacts.insert(op.uri(), artifact);
Ok(false)
}
pub async fn parse(
op: Operation,
dep: URI,
artifacts: Arc<Mutex<ArtifactMap>>,
) -> Result<bool, AppError> {
let Operation::Parse { .. } = &op else {
unreachable!()
};
let artifacts = artifacts.lock().expect("poisoned lock");
let content = artifacts.get(&dep).expect("no parse dependency");
match content {
Artifact::String(content) => {
let _ast = parser::parse(content).map(Artifact::Ast)?;
}
_ => todo!(),
}
Ok(false)
}