Single-commit clean baseline after security scrub of niche-tells, project codenames, internal jargon, and contributor-email leaks. Contents: - 100 Rust crates (_primitives/_rust/) - 37 agent manifests (_manifests/) + generated specs (_generated/) - 67 user-invocable skills (skills/) - 33 hooks (hooks/) - Composition blocks (_blocks/) - Documentation (docs/, README.md) - TS adapter packages (_ts_packages/) - Assembler (_assembler/) - Roles (_roles/) - Templates (_templates/) - Forgejo CI (.forgejo/) Author: Denis Parfionovich <info@greendragon.info> License: see LICENSE.
54 lines
1.7 KiB
Rust
54 lines
1.7 KiB
Rust
//! Shared helpers for the integration tests.
|
|
//!
|
|
//! `tests/` files are separate crates; common code lives under
|
|
//! `tests/common/mod.rs` per cargo convention (not a top-level
|
|
//! `tests/common.rs`, which would itself be a test binary).
|
|
|
|
use kei_watch::Watcher;
|
|
use std::fs;
|
|
use std::path::{Path, PathBuf};
|
|
use std::time::{Duration, Instant};
|
|
|
|
pub const EVENT_TIMEOUT: Duration = Duration::from_secs(3);
|
|
|
|
/// Pull events until one matches `pred` or the global timeout elapses.
|
|
pub fn wait_for<F: Fn(&kei_watch::Event) -> bool>(
|
|
w: &Watcher,
|
|
pred: F,
|
|
) -> Option<kei_watch::Event> {
|
|
let deadline = Instant::now() + EVENT_TIMEOUT;
|
|
while Instant::now() < deadline {
|
|
let remaining = deadline.saturating_duration_since(Instant::now());
|
|
let step = std::cmp::min(remaining, Duration::from_millis(200));
|
|
if let Some(ev) = w.next_event(step) {
|
|
if pred(&ev) {
|
|
return Some(ev);
|
|
}
|
|
}
|
|
}
|
|
None
|
|
}
|
|
|
|
/// macOS reports paths under `/private/var/...`; tempdirs live at `/var/...`.
|
|
/// Canonicalise both sides before compare. When the target file has been
|
|
/// deleted, `canonicalize` fails — fall back to symlink-free parent match.
|
|
pub fn same_path(a: &Path, b: &Path) -> bool {
|
|
if a == b {
|
|
return true;
|
|
}
|
|
let ca = fs::canonicalize(a).ok();
|
|
let cb = fs::canonicalize(b).ok();
|
|
match (ca, cb) {
|
|
(Some(x), Some(y)) => x == y,
|
|
_ => canonicalize_parent(a) == canonicalize_parent(b),
|
|
}
|
|
}
|
|
|
|
fn canonicalize_parent(p: &Path) -> PathBuf {
|
|
let parent = p.parent().and_then(|q| fs::canonicalize(q).ok());
|
|
let file = p.file_name().map(|s| s.to_owned());
|
|
match (parent, file) {
|
|
(Some(par), Some(f)) => par.join(f),
|
|
_ => p.to_path_buf(),
|
|
}
|
|
}
|