use crate::config_edit::branch::{config_branches, config_file, governing_config};
use crate::model_pick::grammar::{self, RoleModel};
use std::path::{Path, PathBuf};
use super::{CONFIG_REF, SKILL_FILE, SKILLS_DIR};
const PROVIDERS: &str = "providers.yaml";
pub fn pool(skills_root: &Path) -> Vec<String> {
let Ok(read) = std::fs::read_dir(skills_root) else {
return Vec::new();
};
let mut names: Vec<String> = read
.flatten()
.filter(|e| e.path().join(SKILL_FILE).is_file())
.map(|e| e.file_name().to_string_lossy().into_owned())
.collect();
names.sort();
names
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ForkPoint {
pub label: String,
pub refspec: String,
pub roles: Vec<RoleModel>,
}
#[derive(Debug, Clone, PartialEq, Eq, Default)]
pub struct Choices {
pub points: Vec<ForkPoint>,
pub skills: Vec<String>,
}
impl Choices {
pub fn point(&self, refspec: &str) -> Option<ForkPoint> {
self.points.iter().find(|p| p.refspec == refspec).cloned()
}
pub fn fireable(&self) -> bool {
self.points.iter().any(|p| !p.roles.is_empty())
}
}
pub fn choices(workspace: &Path, pinned_commit: &str, skills_root: &Path) -> Choices {
let mut points = vec![point(
"here".to_owned(),
pinned_commit.to_owned(),
workspace,
)];
for branch in config_branches(workspace).unwrap_or_default() {
let refspec = format!("{CONFIG_REF}{}", branch.name);
points.push(point(branch.name, refspec, workspace));
}
Choices {
points,
skills: pool(skills_root),
}
}
fn point(label: String, refspec: String, workspace: &Path) -> ForkPoint {
ForkPoint {
roles: roles_at(workspace, &refspec),
label,
refspec,
}
}
pub fn roles_at(workspace: &Path, refspec: &str) -> Vec<RoleModel> {
let Ok(gov) = governing_config(workspace, refspec) else {
return Vec::new();
};
let Ok(bytes) = config_file(workspace, &gov.oid, PROVIDERS) else {
return Vec::new();
};
grammar::roles(&String::from_utf8_lossy(&bytes))
}
pub fn skills_root(yog_data_root: &Path) -> PathBuf {
let world = crate::world::layout_under(yog_data_root);
world.litany.join(SKILLS_DIR)
}