char/avril

(wip) why'd you have to go and make things so complicaaaaated?

git clone https://git.t4t.associates/char/avril

Charlotte Somdeslop: consolidate public type and registry test utils7325e8c

main
3.8 KiB122 linesraw
1use std::cell::RefCell;
2use std::collections::HashMap;
3use std::path::PathBuf;
4use std::rc::Rc;
5
6use avril_core::{Extension, Op, PublicModule};
7use serde::Deserialize;
8
9#[derive(Default)]
10struct Sessions {
11    next: u32,
12    executions: HashMap<u32, avril_task::Execution>,
13}
14
15type Shared = Rc<RefCell<Sessions>>;
16
17#[derive(Deserialize)]
18struct BeginArgs {
19    graph: avril_task::Graph,
20    root: String,
21    target: String,
22    #[serde(default)]
23    args: Vec<String>,
24    #[serde(default)]
25    force: bool,
26    cache_dir: String,
27}
28
29#[derive(Deserialize)]
30struct FinishArgs {
31    session: u32,
32    name: String,
33    code: u8,
34}
35
36#[derive(Deserialize)]
37struct RelevantPath {
38    path: String,
39    #[serde(default)]
40    structural: bool,
41}
42
43#[derive(Deserialize)]
44struct RelevantArgs {
45    graph: avril_task::Graph,
46    target: String,
47    root: String,
48    paths: Vec<RelevantPath>,
49}
50
51fn begin(state: &Shared, args: BeginArgs) -> Result<u32, avril_task::Error> {
52    let mut options = avril_task::RunOptions::new(PathBuf::from(&args.root));
53    options.cache = Some(avril_task::Cache::new(PathBuf::from(&args.cache_dir)));
54    options.force = args.force;
55    options.extra_args = args.args;
56    let execution = avril_task::Execution::new(args.graph, &args.target, options)?;
57    let mut sessions = state.borrow_mut();
58    sessions.next += 1;
59    let id = sessions.next;
60    sessions.executions.insert(id, execution);
61    Ok(id)
62}
63
64fn relevant(args: RelevantArgs) -> Result<bool, avril_task::Error> {
65    let root = PathBuf::from(&args.root);
66    let set = args.graph.watch_set(&args.target, &root)?;
67    Ok(args.paths.iter().any(|candidate| {
68        set.is_relevant_to_callback(&root, &PathBuf::from(&candidate.path), candidate.structural)
69    }))
70}
71
72pub fn init() -> Extension {
73    let sessions: Shared = Rc::new(RefCell::new(Sessions::default()));
74    let begin_state = sessions.clone();
75    let step_state = sessions.clone();
76    let finish_state = sessions.clone();
77    let drop_state = sessions.clone();
78    Extension {
79        name: "ext:task",
80        dependencies: &["ext:base", "ext:file", "ext:process", "ext:timers"],
81        ops: vec![
82            Op::new("op_task_begin", move |args: BeginArgs| {
83                begin(&begin_state, args)
84            }),
85            Op::new("op_task_step", move |session: u32| {
86                let mut sessions = step_state.borrow_mut();
87                let execution = sessions
88                    .executions
89                    .get_mut(&session)
90                    .ok_or_else(|| std::io::Error::other("Unknown task session"))?;
91                execution
92                    .step()
93                    .map_err(|error| std::io::Error::other(error.to_string()))
94            }),
95            Op::new("op_task_finish", move |args: FinishArgs| {
96                let mut sessions = finish_state.borrow_mut();
97                if let Some(execution) = sessions.executions.get_mut(&args.session) {
98                    execution.finish(&args.name, args.code);
99                }
100                Ok::<_, std::io::Error>(())
101            }),
102            Op::new("op_task_drop", move |session: u32| {
103                Ok::<_, std::io::Error>(
104                    drop_state
105                        .borrow_mut()
106                        .executions
107                        .remove(&session)
108                        .is_some(),
109                )
110            }),
111            Op::new("op_task_digest", |graph: avril_task::Graph| {
112                Ok::<_, std::io::Error>(graph.digest())
113            }),
114            Op::new("op_task_relevant", |args: RelevantArgs| relevant(args)),
115        ],
116        modules: const { &[PUBLIC_MODULES[0].module] },
117        entry_point: Some("ext:task/main.js"),
118    }
119}
120
121pub const PUBLIC_MODULES: &[PublicModule] =
122    &[avril_core::public_module!("avril:task", "ext:task", "main")];