use std::path::PathBuf;
const PKGS: &[&str] = &[
"tree-sitter",
"tree-sitter-rust",
"tree-sitter-python",
"tree-sitter-javascript",
"tree-sitter-c",
];
fn main() {
let stamp = find_lock()
.and_then(|p| stamp_from_lock(&p))
.unwrap_or_else(|| "nolock".to_string());
println!("cargo:rustc-env=QUARB_GRAMMAR_STAMP={stamp}");
}
fn find_lock() -> Option<PathBuf> {
let mut dir = PathBuf::from(std::env::var_os("CARGO_MANIFEST_DIR")?);
loop {
let lock = dir.join("Cargo.lock");
if lock.is_file() {
println!("cargo:rerun-if-changed={}", lock.display());
return Some(lock);
}
if !dir.pop() {
return None;
}
}
}
fn stamp_from_lock(path: &PathBuf) -> Option<String> {
let text = std::fs::read_to_string(path).ok()?;
let mut cur_name: Option<String> = None;
let mut versions: Vec<(String, String)> = Vec::new();
for line in text.lines() {
let line = line.trim();
if line == "[[package]]" {
cur_name = None;
} else if let Some(rest) = line.strip_prefix("name = ") {
cur_name = Some(rest.trim_matches('"').to_string());
} else if let Some(rest) = line.strip_prefix("version = ")
&& let Some(name) = &cur_name
&& PKGS.contains(&name.as_str())
{
versions.push((name.clone(), rest.trim_matches('"').to_string()));
}
}
versions.sort();
let stamp = versions
.iter()
.map(|(n, v)| format!("{n}={v}"))
.collect::<Vec<_>>()
.join(";");
Some(if stamp.is_empty() {
"nogrammar".into()
} else {
stamp
})
}