Find an attestation by hash or hash prefix.
(&self, repo: &Repository, prefix: &str)
| 447 | |
| 448 | /// Find an attestation by hash or hash prefix. |
| 449 | fn find_by_prefix(&self, repo: &Repository, prefix: &str) -> CliResult<(Hash, Attestation)> { |
| 450 | // Try exact match first |
| 451 | if let Some(hash) = Hash::from_base32(prefix.as_bytes()) { |
| 452 | if let Ok(attest) = repo.load_attestation(&hash) { |
| 453 | return Ok((hash, attest)); |
| 454 | } |
| 455 | } |
| 456 | |
| 457 | // Prefix search |
| 458 | let prefix_lower = prefix.to_uppercase(); |
| 459 | let mut matches: Vec<(Hash, Attestation)> = Vec::new(); |
| 460 | |
| 461 | for result in repo.change_store().iter_attestations() { |
| 462 | let hash = match result { |
| 463 | Ok(h) => h, |
| 464 | Err(_) => continue, |
| 465 | }; |
| 466 | |
| 467 | let hash_str = hash.to_base32(); |
| 468 | if hash_str.starts_with(&prefix_lower) { |
| 469 | if let Ok(attest) = repo.load_attestation(&hash) { |
| 470 | matches.push((hash, attest)); |
| 471 | } |
| 472 | } |
| 473 | } |
| 474 | |
| 475 | match matches.len() { |
| 476 | 0 => Err(CliError::InvalidArgument { |
| 477 | message: format!("No attestation found matching '{}'", prefix), |
| 478 | }), |
| 479 | 1 => Ok(matches.into_iter().next().unwrap()), |
| 480 | n => Err(CliError::InvalidArgument { |
| 481 | message: format!( |
| 482 | "Ambiguous hash prefix '{}' matches {} attestations. Be more specific.", |
| 483 | prefix, n, |
| 484 | ), |
| 485 | }), |
| 486 | } |
| 487 | } |
| 488 | |
| 489 | /// Print a one-line summary of an attestation. |
| 490 | fn print_summary(&self, hash: &Hash, attest: &Attestation) { |
no test coverage detected