Refactor into cargo-project

Rather than have this logic in the aiken binary, this provides a generic
mechanism to do "something" on file change events.  KtorZ is going to
handle wiring it up to the CLI in the best way for the project.

I tried to write some tests for this, but it's hard to isolate the
watcher logic without wrestling with the borrow checker, or overly
neutering this utility.
This commit is contained in:
Pi Lanningham
2023-11-10 21:35:55 -05:00
committed by KtorZ
parent 771f6d1601
commit 5068da3a17
7 changed files with 122 additions and 83 deletions

View File

@@ -25,7 +25,6 @@ hex = "0.4.3"
ignore = "0.4.20"
indoc = "2.0"
miette = { version = "5.5.0", features = ["fancy"] }
notify = "6.1.1"
owo-colors = { version = "3.5.0", features = ["supports-colors"] }
pallas-addresses = "0.18.0"
pallas-codec = "0.18.0"

View File

@@ -12,7 +12,6 @@ pub mod new;
pub mod packages;
pub mod tx;
pub mod uplc;
pub mod watch;
/// Aiken: a smart-contract language and toolchain for Cardano
#[derive(Parser)]
@@ -24,7 +23,6 @@ pub enum Cmd {
Build(build::Args),
Address(blueprint::address::Args),
Check(check::Args),
Watch(watch::Args),
Docs(docs::Args),
Add(packages::add::Args),

View File

@@ -1,78 +0,0 @@
use notify::{event::EventAttributes, Event, RecursiveMode, Watcher};
use std::{
collections::VecDeque,
path::Path,
sync::{Arc, Mutex},
};
#[derive(clap::Args)]
/// Type-check an Aiken project
pub struct Args {
/// Clear the screen between each run
#[clap(long)]
clear: bool,
}
pub fn exec(Args { clear }: Args) -> miette::Result<()> {
let project = Path::new("../sundae-contracts/aiken")
.to_path_buf()
.canonicalize()
.expect("");
let build = project.join("build").canonicalize().expect("");
let lock = project.join("aiken.lock");
let queue = Arc::new(Mutex::new(VecDeque::new()));
queue.lock().unwrap().push_back(Event {
kind: notify::EventKind::Any,
paths: vec![],
attrs: EventAttributes::new(),
});
let queue_write = queue.clone();
let mut watcher = notify::recommended_watcher(move |res: notify::Result<Event>| {
match res {
Ok(event) => match event.kind {
notify::EventKind::Create(_)
| notify::EventKind::Modify(_)
| notify::EventKind::Remove(_) => {
let mut queue = queue_write.lock().expect("lock queue");
queue.push_back(event.clone());
drop(queue);
}
_ => {}
},
Err(e) => {
println!("watch error: {:?}", e)
}
};
})
.expect("watcher");
let _ = watcher.watch(
Path::new("../sundae-contracts/aiken"),
RecursiveMode::Recursive,
);
let queue_read = queue.clone();
loop {
std::thread::sleep(std::time::Duration::from_millis(300));
let mut queue = queue_read.lock().expect("lock queue");
let mut latest = None;
// debounce the events, and ignore build/lock changes, because they come in in large batches
while let Some(evt) = queue.pop_back() {
if evt.paths.iter().any(|p| {
let p = p.canonicalize().expect("");
p.starts_with(&build) || p.starts_with(&lock)
}) {
continue;
}
latest = Some(evt);
}
drop(queue);
if latest.is_some() {
if clear {
println!("{esc}c", esc = 27 as char);
}
let _ = crate::with_project_ok(Some(project.clone()), false, |p| {
p.check(false, None, true, false, false.into())
});
}
}
}

View File

@@ -2,7 +2,7 @@ use aiken::cmd::{
blueprint::{self, address},
build, check, completion, docs, fmt, lsp, new,
packages::{self, add},
tx, uplc, watch, Cmd,
tx, uplc, Cmd,
};
use aiken_project::{config, pretty};
@@ -17,7 +17,6 @@ fn main() -> miette::Result<()> {
Cmd::Build(args) => build::exec(args),
Cmd::Address(args) => address::exec(args),
Cmd::Check(args) => check::exec(args),
Cmd::Watch(args) => watch::exec(args),
Cmd::Docs(args) => docs::exec(args),
Cmd::Add(args) => add::exec(args),
Cmd::Blueprint(args) => blueprint::exec(args),