Support more flexible version detection

This commit is contained in:
Wildan M 2026-03-14 09:16:31 +07:00
parent 371d751e3e
commit 943cb2cbd0
No known key found for this signature in database
GPG Key ID: 01AC53185C679C79
2 changed files with 99 additions and 41 deletions

View File

@ -12,7 +12,7 @@ use crate::{
config::CookConfig,
cook::{fetch, fs::*, pty::PtyOut},
log_to_pty,
recipe::{BuildKind, CookRecipe, OptionalPackageRecipe, Recipe},
recipe::{BuildKind, CookRecipe, OptionalPackageRecipe},
};
pub fn package(
@ -192,7 +192,7 @@ pub fn package_toml(
let package = Package {
name: recipe.name.with_prefix(PackagePrefix::Any),
version: package_version(&recipe.recipe),
version: recipe.guess_version().unwrap_or("TODO".into()),
target: recipe.target.to_string(),
blake3: hash,
network_size,
@ -208,22 +208,6 @@ pub fn package_toml(
return Ok(());
}
fn package_version(recipe: &Recipe) -> String {
if recipe.build.kind == BuildKind::None {
"".into()
} else if let Some(v) = &recipe.package.version {
v.to_string()
} else if let Some(r) = &recipe.source {
if let Some(m) = r.guess_version() {
m
} else {
"TODO".into()
}
} else {
"TODO".into()
}
}
pub fn package_target(name: &PackageName) -> &'static str {
if name.is_host() {
redoxer::host_target()

View File

@ -66,26 +66,6 @@ pub enum SourceRecipe {
},
}
impl SourceRecipe {
pub fn guess_version(&self) -> Option<String> {
match self {
SourceRecipe::Tar {
tar,
blake3: _,
patches: _,
script: _,
} => {
let re = Regex::new(r"\d+\.\d+\.\d+").unwrap();
if let Some(arm) = re.captures(&tar) {
return Some(arm.get(0).unwrap().as_str().to_string());
}
None
}
_ => None,
}
}
}
/// Specifies how to build a recipe
#[derive(Debug, Clone, Deserialize, PartialEq, Serialize)]
#[serde(tag = "template")]
@ -498,6 +478,62 @@ impl CookRecipe {
Ok(())
}
pub fn guess_version(&self) -> Option<String> {
let recipe = &self.recipe;
if recipe.build.kind == BuildKind::None {
return Some("".into()); // signifies a meta package
} else if let Some(v) = &recipe.package.version {
return Some(v.to_string());
}
let re = VersionExtractor::new();
let mut dir = self.dir.to_path_buf();
if let Some(r) = &recipe.source {
match r {
SourceRecipe::Tar {
tar,
blake3: _,
patches: _,
script: _,
} => {
if let Some(ver) = re.extract_ver(&tar) {
return Some(ver);
}
}
SourceRecipe::Git {
git: _,
upstream: _,
branch,
rev,
shallow_clone: _,
patches: _,
script: _,
} => {
if let Some(rev) = rev {
if let Some(ver) = re.extract_ver(&rev) {
return Some(ver);
}
}
if let Some(branch) = branch {
if let Some(ver) = re.extract_ver(&branch) {
return Some(ver);
}
}
}
SourceRecipe::SameAs { same_as } => {
dir = self.dir.join(same_as);
}
_ => {}
}
};
let cargo_path = dir.join("source/Cargo.toml");
if let Some(ver) = VersionExtractor::extract_cargo_ver(&cargo_path) {
return Some(ver);
}
None
}
}
// TODO: Wrap these vectors in a struct
@ -531,6 +567,47 @@ pub struct AutoDeps {
pub packages: BTreeSet<PackageName>,
}
pub struct VersionExtractor {
regex: Regex,
}
impl VersionExtractor {
pub fn new() -> Self {
Self {
regex: Regex::new(r"\d+(\.\d+){1,2}").unwrap(),
}
}
pub fn extract_ver(&self, text: &str) -> Option<String> {
if let Some(arm) = self.regex.captures(&text) {
return Some(arm.get(0)?.as_str().to_string());
}
None
}
fn extract_cargo_ver(path: &Path) -> Option<String> {
let content = std::fs::read_to_string(path).ok()?;
let manifest = content.parse::<toml::Table>().ok()?;
if let Some(version) = manifest
.get("package")
.and_then(|pkg| pkg.get("version"))
.and_then(|v| v.as_str())
{
return Some(version.to_string());
}
if let Some(version) = manifest
.get("workspace")
.and_then(|ws| ws.get("package"))
.and_then(|pkg| pkg.get("version"))
.and_then(|v| v.as_str())
{
return Some(version.to_string());
}
None
}
}
#[cfg(test)]
mod tests {
use pkg::PackageName;
@ -610,9 +687,6 @@ mod tests {
..Default::default()
}
);
let source = recipe.source.unwrap();
assert_eq!(source.guess_version(), Some("1.3.3".to_string()));
}
#[test]