fix: cubl exact-match AUR search, numbered ambiguity menu, PKGBUILD-not-found handling

This commit is contained in:
2026-05-08 07:32:38 +01:00
parent 2b984db9a1
commit cbdcd101c1
@@ -372,20 +372,38 @@ fn install_package(context: &AppContext, package: &str) -> Result<(), Box<dyn st
if cfg!(not(target_os = "redox")) { if cfg!(not(target_os = "redox")) {
println!("Searching AUR for {package}..."); println!("Searching AUR for {package}...");
let client = AurClient::new(); let client = AurClient::new();
let results = client.search(package, Some("name"))?; let results = client.search(package, Some("name-desc"))?;
if results.is_empty() { if results.is_empty() {
return Err(format!("{package} not found in AUR").into()); return Err(format!("{package} not found in AUR").into());
} }
let pkg = &results[0]; let exact = results.iter().find(|p| p.name == package);
let pkg = exact.unwrap_or(&results[0]);
if exact.is_none() && results.len() > 1 {
println!("No exact match for '{package}'. Closest results:");
for (i, r) in results.iter().take(5).enumerate() {
println!(" {}. {}/{}{}", i + 1, r.name, r.version, r.description);
}
println!("Enter number to select (or 0 to skip): ");
let mut choice = String::new();
io::stdin().read_line(&mut choice)?;
if let Ok(n) = choice.trim().parse::<usize>() {
if n > 0 && n <= results.len().min(5) {
let selected = &results[n - 1];
println!("Selected: {}/{}", selected.name, selected.version);
fetch_and_save_aur(selected)?;
}
}
return Ok(());
}
println!("Found: {}/{}{}", pkg.name, pkg.version, pkg.description); println!("Found: {}/{}{}", pkg.name, pkg.version, pkg.description);
println!("Would you like to fetch this package from AUR into ~/.cub/? [y/N]"); println!("Would you like to fetch this package from AUR into ~/.cub/? [y/N]");
let mut answer = String::new(); let mut answer = String::new();
io::stdin().read_line(&mut answer)?; io::stdin().read_line(&mut answer)?;
if answer.trim().to_ascii_lowercase().starts_with('y') { if answer.trim().to_ascii_lowercase().starts_with('y') {
fetch_aur_to_store(&pkg.name)?; fetch_and_save_aur(pkg)?;
println!("Recipe saved to ~/.cub/recipes/{}/", pkg.name);
println!("Build with: cubl -B ~/.cub/recipes/{}/", pkg.name);
} }
return Ok(()); return Ok(());
} }
@@ -697,6 +715,13 @@ fn fetch_aur_to_store(package: &str) -> Result<(), Box<dyn std::error::Error>> {
} }
let pkgbuild_path = clone_dir.join("PKGBUILD"); let pkgbuild_path = clone_dir.join("PKGBUILD");
if !pkgbuild_path.exists() {
return Err(Box::new(CubError::PackageNotFound(format!(
"AUR repository cloned but PKGBUILD not found at {}. The package may be a split package or empty.",
pkgbuild_path.display()
))));
}
let pkgbuild_content = fs::read_to_string(&pkgbuild_path)?; let pkgbuild_content = fs::read_to_string(&pkgbuild_path)?;
let conversion = pkgbuild::convert_pkgbuild(&pkgbuild_content)?; let conversion = pkgbuild::convert_pkgbuild(&pkgbuild_content)?;
@@ -707,6 +732,21 @@ fn fetch_aur_to_store(package: &str) -> Result<(), Box<dyn std::error::Error>> {
Ok(()) Ok(())
} }
fn fetch_and_save_aur(pkg: &AurPackage) -> Result<(), Box<dyn std::error::Error>> {
match fetch_aur_to_store(&pkg.name) {
Ok(()) => {
println!("Recipe saved to ~/.cub/recipes/{}/", pkg.name);
println!("Build with: cubl -B ~/.cub/recipes/{}/", pkg.name);
Ok(())
}
Err(e) => {
eprintln!("Failed to fetch {name}: {e}", name = pkg.name);
eprintln!("Try manual import: cubl --import-aur {name}", name = pkg.name);
Err(e)
}
}
}
fn fetch_bur_recipe(package: &str) -> Result<(), Box<dyn std::error::Error>> { fn fetch_bur_recipe(package: &str) -> Result<(), Box<dyn std::error::Error>> {
let source_dir = ensure_bur_package_dir(package)?; let source_dir = ensure_bur_package_dir(package)?;
let destination = env::current_dir()?.join(package); let destination = env::current_dir()?.join(package);