diff options
| author | nsfisis <nsfisis@gmail.com> | 2026-05-19 00:10:22 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2026-05-19 00:11:03 +0900 |
| commit | c839244d8d09f3036ebfee8eef7eb6b147e593ab (patch) | |
| tree | fe48c94f2c2e62468beef5ff1a8f3cff6adeef4f /crates/shirabe/src/advisory | |
| parent | 48839250146b217e2756ed3c0e624fd341b54d6c (diff) | |
| download | php-shirabe-c839244d8d09f3036ebfee8eef7eb6b147e593ab.tar.gz php-shirabe-c839244d8d09f3036ebfee8eef7eb6b147e593ab.tar.zst php-shirabe-c839244d8d09f3036ebfee8eef7eb6b147e593ab.zip | |
fix(compile): fix various compile errors
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Diffstat (limited to 'crates/shirabe/src/advisory')
| -rw-r--r-- | crates/shirabe/src/advisory/audit_config.rs | 8 | ||||
| -rw-r--r-- | crates/shirabe/src/advisory/auditor.rs | 145 | ||||
| -rw-r--r-- | crates/shirabe/src/advisory/ignored_security_advisory.rs | 15 | ||||
| -rw-r--r-- | crates/shirabe/src/advisory/partial_security_advisory.rs | 17 | ||||
| -rw-r--r-- | crates/shirabe/src/advisory/security_advisory.rs | 7 |
5 files changed, 76 insertions, 116 deletions
diff --git a/crates/shirabe/src/advisory/audit_config.rs b/crates/shirabe/src/advisory/audit_config.rs index f75d499..bdf3e8d 100644 --- a/crates/shirabe/src/advisory/audit_config.rs +++ b/crates/shirabe/src/advisory/audit_config.rs @@ -6,7 +6,7 @@ use shirabe_php_shim::{InvalidArgumentException, PhpMixed}; use crate::advisory::auditor::Auditor; use crate::config::Config; -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct AuditConfig { pub audit: bool, pub audit_format: String, @@ -123,7 +123,11 @@ impl AuditConfig { Ok((for_audit, for_block)) } - pub fn from_config(config: &Config, audit: bool, audit_format: &str) -> anyhow::Result<Self> { + pub fn from_config( + config: &mut Config, + audit: bool, + audit_format: &str, + ) -> anyhow::Result<Self> { let audit_config_raw = config.get("audit"); let audit_config = audit_config_raw.as_array(); diff --git a/crates/shirabe/src/advisory/auditor.rs b/crates/shirabe/src/advisory/auditor.rs index e1b40c2..68bedb0 100644 --- a/crates/shirabe/src/advisory/auditor.rs +++ b/crates/shirabe/src/advisory/auditor.rs @@ -70,7 +70,7 @@ impl Auditor { /// @throws InvalidArgumentException If no packages are passed in pub fn audit( &self, - io: &dyn IOInterface, + io: &mut dyn IOInterface, repo_set: &RepositorySet, packages: Vec<Box<dyn PackageInterface>>, format: &str, @@ -170,17 +170,13 @@ impl Auditor { ), ); - io.write( - PhpMixed::String(JsonFile::encode( - &PhpMixed::Array(json.into_iter().map(|(k, v)| (k, Box::new(v))).collect()), - shirabe_php_shim::JSON_UNESCAPED_SLASHES - | shirabe_php_shim::JSON_PRETTY_PRINT - | shirabe_php_shim::JSON_UNESCAPED_UNICODE, - JsonFile::INDENT_DEFAULT, - )), - true, - io_interface::NORMAL, - ); + io.write(&JsonFile::encode_with_indent( + &PhpMixed::Array(json.into_iter().map(|(k, v)| (k, Box::new(v))).collect()), + shirabe_php_shim::JSON_UNESCAPED_SLASHES + | shirabe_php_shim::JSON_PRETTY_PRINT + | shirabe_php_shim::JSON_UNESCAPED_UNICODE, + JsonFile::INDENT_DEFAULT, + )); return Ok(audit_bitmask); } @@ -214,57 +210,31 @@ impl Auditor { }; let pkg_plurality = if pkg_count == 1 { "" } else { "s" }; let punctuation = if format == "summary" { "." } else { ":" }; - io.write_error( - PhpMixed::String(sprintf( - &message, - &[ - PhpMixed::Int(total_advisory_count), - PhpMixed::String(plurality.to_string()), - PhpMixed::Int(pkg_count), - PhpMixed::String(pkg_plurality.to_string()), - PhpMixed::String(punctuation.to_string()), - ], - )), - true, - io_interface::NORMAL, - ); + io.write_error(&sprintf( + &message, + &[ + PhpMixed::Int(total_advisory_count), + PhpMixed::String(plurality.to_string()), + PhpMixed::Int(pkg_count), + PhpMixed::String(pkg_plurality.to_string()), + PhpMixed::String(punctuation.to_string()), + ], + )); self.output_advisories(io, advisories_to_output, format)?; } } if format == Self::FORMAT_SUMMARY { - io.write_error( - PhpMixed::String( - "Run \"composer audit\" for a full list of advisories.".to_string(), - ), - true, - io_interface::NORMAL, - ); + io.write_error("Run \"composer audit\" for a full list of advisories."); } } else { - io.write_error( - PhpMixed::String( - "<info>No security vulnerability advisories found.</info>".to_string(), - ), - true, - io_interface::NORMAL, - ); + io.write_error("<info>No security vulnerability advisories found.</info>"); } if !unreachable_repos.is_empty() { - io.write_error( - PhpMixed::String( - "<warning>The following repositories were unreachable:</warning>".to_string(), - ), - true, - io_interface::NORMAL, - ); + io.write_error("<warning>The following repositories were unreachable:</warning>"); for repo in &unreachable_repos { - io.write_error( - PhpMixed::String(format!(" - {}", repo)), - true, - io_interface::NORMAL, - ); + io.write_error(&format!(" - {}", repo)); } } @@ -458,7 +428,7 @@ impl Auditor { /// @param self::FORMAT_* $format The format that will be used to output audit results. fn output_advisories( &self, - io: &dyn IOInterface, + io: &mut dyn IOInterface, advisories: &IndexMap<String, Vec<PartialSecurityAdvisory>>, format: &str, ) -> Result<()> { @@ -534,8 +504,8 @@ impl Auditor { } let _ = row; io.get_table() - .set_horizontal() - .set_headers(headers) + .set_horizontal(true) + .set_headers(headers.into_iter().map(|h| h.into()).collect()) .add_row(ConsoleIO::sanitize(PhpMixed::Null, false)) .set_column_width(1, 80) .set_column_max_width(1, 80) @@ -547,7 +517,7 @@ impl Auditor { /// @param array<string, array<SecurityAdvisory>> $advisories fn output_advisories_plain( &self, - io: &dyn IOInterface, + io: &mut dyn IOInterface, advisories: &IndexMap<String, Vec<PartialSecurityAdvisory>>, ) { let mut error: Vec<String> = vec![]; @@ -596,41 +566,30 @@ impl Auditor { first_advisory = false; } } - io.write_error( - PhpMixed::List( - error - .into_iter() - .map(|s| Box::new(PhpMixed::String(s))) - .collect(), - ), - true, - io_interface::NORMAL, - ); + for line in &error { + io.write_error(line); + } } /// @param array<CompletePackageInterface> $packages /// @param self::FORMAT_PLAIN|self::FORMAT_TABLE $format fn output_abandoned_packages( &self, - io: &dyn IOInterface, + io: &mut dyn IOInterface, packages: &[Box<dyn CompletePackageInterface>], format: &str, ) -> Result<()> { - io.write_error( - PhpMixed::String(sprintf( - "<error>Found %d abandoned package%s:</error>", - &[ - PhpMixed::Int(packages.len() as i64), - PhpMixed::String(if packages.len() > 1 { - "s".to_string() - } else { - String::new() - }), - ], - )), - true, - io_interface::NORMAL, - ); + io.write_error(&sprintf( + "<error>Found %d abandoned package%s:</error>", + &[ + PhpMixed::Int(packages.len() as i64), + PhpMixed::String(if packages.len() > 1 { + "s".to_string() + } else { + String::new() + }), + ], + )); if format == Self::FORMAT_PLAIN { for pkg in packages { @@ -639,17 +598,13 @@ impl Auditor { } else { "No replacement was suggested".to_string() }; - io.write_error( - PhpMixed::String(sprintf( - "%s is abandoned. %s.", - &[ - PhpMixed::String(self.get_package_name_with_link_for_complete(pkg)), - PhpMixed::String(replacement), - ], - )), - true, - io_interface::NORMAL, - ); + io.write_error(&sprintf( + "%s is abandoned. %s.", + &[ + PhpMixed::String(self.get_package_name_with_link_for_complete(pkg)), + PhpMixed::String(replacement), + ], + )); } return Ok(()); @@ -672,8 +627,8 @@ impl Auditor { .unwrap() .get_table() .set_headers(vec![ - "Abandoned Package".to_string(), - "Suggested Replacement".to_string(), + "Abandoned Package".to_string().into(), + "Suggested Replacement".to_string().into(), ]) .set_column_width(1, 80) .set_column_max_width(1, 80); diff --git a/crates/shirabe/src/advisory/ignored_security_advisory.rs b/crates/shirabe/src/advisory/ignored_security_advisory.rs index 7ed3a4c..03e7d78 100644 --- a/crates/shirabe/src/advisory/ignored_security_advisory.rs +++ b/crates/shirabe/src/advisory/ignored_security_advisory.rs @@ -6,9 +6,12 @@ use indexmap::IndexMap; use shirabe_php_shim::PhpMixed; use shirabe_semver::constraint::constraint_interface::ConstraintInterface; -#[derive(Debug)] +#[derive(Debug, serde::Serialize)] +#[serde(rename_all = "camelCase")] pub struct IgnoredSecurityAdvisory { + #[serde(flatten)] inner: SecurityAdvisory, + #[serde(skip_serializing_if = "Option::is_none")] pub ignore_reason: Option<String>, } @@ -41,14 +44,4 @@ impl IgnoredSecurityAdvisory { ignore_reason, } } - - pub fn json_serialize(&self) -> PhpMixed { - let mut data = self.inner.json_serialize(); - if self.ignore_reason.is_none() { - if let PhpMixed::Array(ref mut map) = data { - map.remove("ignoreReason"); - } - } - data - } } diff --git a/crates/shirabe/src/advisory/partial_security_advisory.rs b/crates/shirabe/src/advisory/partial_security_advisory.rs index e7aa96e..a47ec02 100644 --- a/crates/shirabe/src/advisory/partial_security_advisory.rs +++ b/crates/shirabe/src/advisory/partial_security_advisory.rs @@ -1,6 +1,7 @@ //! ref: composer/src/Composer/Advisory/PartialSecurityAdvisory.php use crate::advisory::security_advisory::SecurityAdvisory; +use crate::repository::advisory_provider_interface::PartialOrSecurityAdvisory; use anyhow::Result; use chrono::{DateTime, TimeZone, Utc}; use indexmap::IndexMap; @@ -31,7 +32,7 @@ impl PartialSecurityAdvisory { package_name: &str, data: &IndexMap<String, PhpMixed>, parser: &VersionParser, - ) -> Result<Box<dyn std::any::Any>> { + ) -> Result<PartialOrSecurityAdvisory> { let affected_versions_str = data["affectedVersions"].as_string().unwrap_or(""); let constraint: Box<dyn ConstraintInterface> = @@ -40,9 +41,12 @@ impl PartialSecurityAdvisory { Err(_) => { let affected_version = Preg::replace(r"(^[>=<^~]*[\d.]+).*", "$1", affected_versions_str); - match parser.parse_constraints(&affected_version) { + match parser.parse_constraints(affected_version.as_deref().unwrap_or("")) { Ok(c) => c, - Err(_) => Box::new(Constraint::new("==", "0.0.0-invalid-version")), + Err(_) => Box::new(Constraint::new( + "==".to_string(), + "0.0.0-invalid-version".to_string(), + )), } } }; @@ -63,7 +67,8 @@ impl PartialSecurityAdvisory { data["advisoryId"].as_string().unwrap_or("").to_string(), constraint, data["title"].as_string().unwrap_or("").to_string(), - data["sources"].clone(), + // TODO(phase-b): parse PhpMixed sources array into Vec<IndexMap<String, String>> + todo!(), reported_at, data.get("cve") .and_then(|v| v.as_string()) @@ -75,10 +80,10 @@ impl PartialSecurityAdvisory { .and_then(|v| v.as_string()) .map(|s| s.to_string()), ); - return Ok(Box::new(advisory)); + return Ok(PartialOrSecurityAdvisory::Full(advisory)); } - Ok(Box::new(Self { + Ok(PartialOrSecurityAdvisory::Partial(Self { advisory_id: data["advisoryId"].as_string().unwrap_or("").to_string(), package_name: package_name.to_string(), affected_versions: constraint, diff --git a/crates/shirabe/src/advisory/security_advisory.rs b/crates/shirabe/src/advisory/security_advisory.rs index 049169d..1b1ff64 100644 --- a/crates/shirabe/src/advisory/security_advisory.rs +++ b/crates/shirabe/src/advisory/security_advisory.rs @@ -44,12 +44,15 @@ impl SecurityAdvisory { } } + pub fn affected_versions(&self) -> &dyn ConstraintInterface { + &*self.inner.affected_versions + } + pub fn to_ignored_advisory(&self, ignore_reason: Option<String>) -> IgnoredSecurityAdvisory { IgnoredSecurityAdvisory::new( self.inner.package_name.clone(), self.inner.advisory_id.clone(), - // TODO: Phase B - handle shared ownership of affected_versions - self.inner.affected_versions.clone(), + self.inner.affected_versions.clone_box(), self.title.clone(), self.sources.clone(), self.reported_at, |
