KeiSeiKit-1.0/_primitives/_rust/kei-fork/src/rescue.rs
Parfii-bot 0be354a920 KeiSeiKit-public — clean state
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.
2026-05-01 12:09:03 +08:00

54 lines
1.6 KiB
Rust

//! `rescue(agent_id, kit_root, out_dir)` — copy a fork's files out of
//! band.
//!
//! Resolution order:
//! 1. `_forks/<id>/` (live) → copy to `out_dir`
//! 2. `_archive/forks/<date>/<id>/` (archived) → copy to `out_dir`
//! 3. Neither → `Error::Gone`
//!
//! Copy is recursive; the destination may pre-exist (we merge on top).
//! Returns the number of regular files copied.
use crate::error::Error;
use std::fs;
use std::path::{Path, PathBuf};
pub fn rescue(agent_id: &str, kit_root: &Path, out_dir: &Path) -> Result<usize, Error> {
let src = locate(agent_id, kit_root).ok_or_else(|| Error::Gone(agent_id.to_string()))?;
fs::create_dir_all(out_dir)?;
Ok(copy_tree(&src, out_dir)?)
}
fn locate(agent_id: &str, kit_root: &Path) -> Option<PathBuf> {
let live = kit_root.join("_forks").join(agent_id);
if live.is_dir() {
return Some(live);
}
let archive_root = kit_root.join("_archive/forks");
let dates = fs::read_dir(&archive_root).ok()?;
for e in dates.flatten() {
let candidate = e.path().join(agent_id);
if candidate.is_dir() {
return Some(candidate);
}
}
None
}
fn copy_tree(src: &Path, dst: &Path) -> std::io::Result<usize> {
let mut n = 0;
for entry in fs::read_dir(src)? {
let entry = entry?;
let name = entry.file_name();
let from = entry.path();
let to = dst.join(&name);
if from.is_dir() {
fs::create_dir_all(&to)?;
n += copy_tree(&from, &to)?;
} else if from.is_file() {
fs::copy(&from, &to)?;
n += 1;
}
}
Ok(n)
}