use std::path::{Path, PathBuf};
use std::process::Command;
fn main() {
println!("cargo:rerun-if-changed=build.rs");
let manifest_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
generate_skill_files(&manifest_dir);
let repo_root = manifest_dir
.ancestors()
.find(|p| p.join(".git").exists())
.map(Path::to_path_buf);
let commit = Command::new("git")
.arg("-C")
.arg(repo_root.as_deref().unwrap_or(&manifest_dir))
.args(["rev-parse", "HEAD"])
.output()
.ok()
.and_then(|o| {
if o.status.success() {
String::from_utf8(o.stdout)
.ok()
.map(|s| s.trim().to_string())
} else {
None
}
})
.filter(|s| !s.is_empty())
.unwrap_or_else(|| "unknown".to_string());
println!("cargo:rustc-env=ORCHESTRATECTL_GIT_COMMIT={commit}");
if let Some(root) = repo_root {
let git_path = root.join(".git");
let git_dir = if git_path.is_dir() {
Some(git_path)
} else if git_path.is_file() {
std::fs::read_to_string(&git_path)
.ok()
.and_then(|s| {
s.lines()
.find_map(|l| l.strip_prefix("gitdir:").map(str::trim).map(str::to_string))
})
.map(PathBuf::from)
.map(|p| if p.is_absolute() { p } else { root.join(p) })
} else {
None
};
if let Some(git_dir) = git_dir {
let head_path = git_dir.join("HEAD");
if let Ok(head) = std::fs::read_to_string(&head_path) {
println!("cargo:rerun-if-changed={}", head_path.display());
if let Some(rest) = head.strip_prefix("ref: ") {
let ref_path = git_dir.join(rest.trim());
println!("cargo:rerun-if-changed={}", ref_path.display());
}
}
}
}
}
fn generate_skill_files(manifest_dir: &Path) {
let cli_version = env!("CARGO_PKG_VERSION");
let out_dir = PathBuf::from(std::env::var_os("OUT_DIR").expect("OUT_DIR"));
let skills_dir = manifest_dir.join("skills");
println!("cargo:rerun-if-changed={}", skills_dir.display());
let entries = std::fs::read_dir(&skills_dir)
.unwrap_or_else(|e| panic!("read {}: {}", skills_dir.display(), e));
for entry in entries.flatten() {
let path = entry.path();
if !path.is_dir() {
continue;
}
let template = path.join("SKILL.template.md");
if !template.exists() {
continue;
}
let name = path.file_name().and_then(|n| n.to_str()).expect("dirname");
let body = std::fs::read_to_string(&template)
.unwrap_or_else(|e| panic!("read {}: {}", template.display(), e));
let rendered = body.replace("{{CLI_VERSION}}", cli_version);
let out_skill_dir = out_dir.join("skills").join(name);
std::fs::create_dir_all(&out_skill_dir)
.unwrap_or_else(|e| panic!("mkdir {}: {}", out_skill_dir.display(), e));
let out_file = out_skill_dir.join("SKILL.md");
std::fs::write(&out_file, &rendered)
.unwrap_or_else(|e| panic!("write {}: {}", out_file.display(), e));
println!("cargo:rerun-if-changed={}", template.display());
println!("cargo:rerun-if-changed={}", path.display());
let files =
std::fs::read_dir(&path).unwrap_or_else(|e| panic!("read {}: {}", path.display(), e));
for file in files.flatten() {
let fpath = file.path();
if !fpath.is_file() {
continue;
}
let is_md = fpath.extension().and_then(|e| e.to_str()) == Some("md");
let fname = match fpath.file_name().and_then(|n| n.to_str()) {
Some(n) if is_md && n != "SKILL.template.md" && n != "SKILL.md" => n.to_string(),
_ => continue,
};
let fbody = std::fs::read_to_string(&fpath)
.unwrap_or_else(|e| panic!("read {}: {}", fpath.display(), e));
let frendered = fbody.replace("{{CLI_VERSION}}", cli_version);
let out_resource = out_skill_dir.join(&fname);
std::fs::write(&out_resource, &frendered)
.unwrap_or_else(|e| panic!("write {}: {}", out_resource.display(), e));
println!("cargo:rerun-if-changed={}", fpath.display());
}
}
}