fix: extract PKGBUILD build()/package() bodies for Custom templates

- extract_bash_function() extracts bash function bodies by brace-matching
- Custom template now populates build_script from build() body
- Custom template now populates install_script from package() body
- Fixes 'custom builds require prepare/build/install instructions' error
This commit is contained in:
2026-05-08 07:39:37 +01:00
parent cbdcd101c1
commit eaf283af36
@@ -58,6 +58,22 @@ pub fn convert_pkgbuild(content: &str) -> Result<ConversionResult, CubError> {
let mut warnings = detect_linuxisms(content);
let mut actions_required = Vec::new();
let build_body = if matches!(template, BuildTemplate::Custom) {
extract_bash_function(content, "build")
} else {
None
};
let package_body = if matches!(template, BuildTemplate::Custom) {
extract_bash_function(content, "package")
} else {
None
};
if template == BuildTemplate::Custom && build_body.is_none() && package_body.is_none() {
warnings.push("Custom build detected but could not extract build() or package() function body".to_string());
actions_required.push("review the PKGBUILD build() and package() functions manually".to_string());
}
let mapped_runtime = map_dep_list(&depends, &mut warnings, &mut actions_required);
let mapped_build = map_dep_list(&makedepends, &mut warnings, &mut actions_required);
let mapped_check = map_dep_list(&checkdepends, &mut warnings, &mut actions_required);
@@ -117,6 +133,8 @@ pub fn convert_pkgbuild(content: &str) -> Result<ConversionResult, CubError> {
},
build: BuildSection {
template,
build_script: build_body.into_iter().collect(),
install_script: package_body.into_iter().collect(),
..BuildSection::default()
},
install: InstallSection::default(),
@@ -326,6 +344,37 @@ pub fn detect_build_template(content: &str) -> BuildTemplate {
}
}
pub fn extract_bash_function(content: &str, name: &str) -> Option<String> {
for pattern in &[format!("{name}() {{"), format!("function {name} () {{"), format!("{name} () {{")] {
if let Some(pos) = content.find(pattern) {
let start = pos + pattern.len();
let rest = &content[start..];
let mut depth = 1u32;
let mut end = 0usize;
for (i, ch) in rest.char_indices() {
match ch {
'{' => depth += 1,
'}' => {
depth -= 1;
if depth == 0 {
end = i;
break;
}
}
_ => {}
}
}
if end > 0 {
let body = rest[..end].trim().to_string();
if !body.is_empty() {
return Some(body);
}
}
}
}
None
}
pub fn detect_linuxisms(content: &str) -> Vec<String> {
let lowered = content.to_ascii_lowercase();
let checks = [