diff options
| author | nsfisis <nsfisis@gmail.com> | 2026-05-08 23:40:37 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2026-05-08 23:41:06 +0900 |
| commit | 18d5a78fee75e0a466355e6edfb634d8f7a7565a (patch) | |
| tree | 68837bab501f8725bd0af1068adb892d2ca7c4dd /crates/mozart-registry/src | |
| parent | d770693bac655da4a21144b4cae7592536fecb8b (diff) | |
| download | php-mozart-18d5a78fee75e0a466355e6edfb634d8f7a7565a.tar.gz php-mozart-18d5a78fee75e0a466355e6edfb634d8f7a7565a.tar.zst php-mozart-18d5a78fee75e0a466355e6edfb634d8f7a7565a.zip | |
fix(require): align with Composer's RequireCommand pipeline
- Add mozart-registry::version_selector::VersionSelector mirroring
Composer\Package\Version\VersionSelector; wraps find_best_candidate
and find_recommended_require_version_string for per-arg resolution
- Decompose execute() into named helpers matching Composer's structure:
CommandState, revert_composer_file, get_inconsistent_require_keys,
get_packages_by_require_key, update_file, update_file_cleanly (stub
for PR 3), do_update, update_requirements_after_resolution (stub for PR 2)
- Fix firstRequire gating: compute first_require from the original file
before applying changes; apply setUpdateAllowList only when
!first_require and lock exists (prevents over-pinning on fresh projects)
- Add --fixed gate: bail when fixed && !dev && type != "project",
matching Composer L173-189 wording verbatim
- Wire --no-security-blocking + COMPOSER_NO_SECURITY_BLOCKING env var
into block_insecure in ResolveRequest (was always false)
- Wire COMPOSER_NO_AUDIT env var to skip audit step (tracked)
- Match Composer's revertComposerFile messaging: "deleting <file>" for
newly-created, "reverting <file> and <lock> to their" / "to its" for
existing files; also removes lock file on newly-created revert
- Auto-create "{\n}\n" when composer.json is missing or empty, mirroring
Composer L138-152; delete file on dry-run cleanup (finally block)
- Add resolution-failure hint: "You can also try re-running mozart
require with an explicit version constraint…" for unversioned packages
- Update deprecated-flag warnings to stderr (write_error) with
Composer-matching wording for --no-suggest
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Diffstat (limited to 'crates/mozart-registry/src')
| -rw-r--r-- | crates/mozart-registry/src/advisory.rs | 31 | ||||
| -rw-r--r-- | crates/mozart-registry/src/lib.rs | 1 | ||||
| -rw-r--r-- | crates/mozart-registry/src/version_selector.rs | 48 |
3 files changed, 65 insertions, 15 deletions
diff --git a/crates/mozart-registry/src/advisory.rs b/crates/mozart-registry/src/advisory.rs index 97242b3..8cf112e 100644 --- a/crates/mozart-registry/src/advisory.rs +++ b/crates/mozart-registry/src/advisory.rs @@ -230,29 +230,30 @@ impl Auditor { } // Check by advisory ID - if is_active - && let Some(reason) = ignore_list.get(&adv.advisory_id) { - is_active = false; - ignore_reason = reason.clone(); - } + if is_active && let Some(reason) = ignore_list.get(&adv.advisory_id) { + is_active = false; + ignore_reason = reason.clone(); + } // Check by severity if is_active && let Some(ref sev) = adv.severity - && let Some(reason) = ignored_severities.get(sev.as_str()) { - is_active = false; - ignore_reason = reason - .clone() - .or_else(|| Some(format!("{sev} severity is ignored"))); - } + && let Some(reason) = ignored_severities.get(sev.as_str()) + { + is_active = false; + ignore_reason = reason + .clone() + .or_else(|| Some(format!("{sev} severity is ignored"))); + } // Check by CVE if is_active && let Some(ref cve) = adv.cve - && let Some(reason) = ignore_list.get(cve.as_str()) { - is_active = false; - ignore_reason = reason.clone(); - } + && let Some(reason) = ignore_list.get(cve.as_str()) + { + is_active = false; + ignore_reason = reason.clone(); + } // Check by source remote IDs if is_active { diff --git a/crates/mozart-registry/src/lib.rs b/crates/mozart-registry/src/lib.rs index 8f9af91..e35056c 100644 --- a/crates/mozart-registry/src/lib.rs +++ b/crates/mozart-registry/src/lib.rs @@ -15,3 +15,4 @@ pub mod repository_filter; pub mod resolver; pub mod vcs_bridge; pub mod version; +pub mod version_selector; diff --git a/crates/mozart-registry/src/version_selector.rs b/crates/mozart-registry/src/version_selector.rs new file mode 100644 index 0000000..7aa409e --- /dev/null +++ b/crates/mozart-registry/src/version_selector.rs @@ -0,0 +1,48 @@ +use crate::cache::Cache; +use crate::packagist::{self, PackagistVersion}; +use crate::version; +use mozart_core::package::Stability; + +/// Mirrors `Composer\Package\Version\VersionSelector`. +pub struct VersionSelector { + preferred_stability: Stability, + repo_cache: Cache, +} + +impl VersionSelector { + pub fn new(preferred_stability: Stability, repo_cache: Cache) -> Self { + Self { + preferred_stability, + repo_cache, + } + } + + /// Fetch versions from Packagist and pick the best candidate. + /// Mirrors `VersionSelector::findBestCandidate()`. + pub async fn find_best_candidate( + &self, + package_name: &str, + ) -> anyhow::Result<Option<PackagistVersion>> { + let versions = packagist::fetch_package_versions(package_name, &self.repo_cache).await?; + Ok(version::find_best_candidate(&versions, self.preferred_stability).cloned()) + } + + /// Generate a recommended constraint string from a concrete version. + /// Mirrors `VersionSelector::findRecommendedRequireVersion()`. + pub fn find_recommended_require_version_string( + &self, + pkg: &PackagistVersion, + fixed: bool, + ) -> String { + if fixed { + pkg.version.clone() + } else { + let stability = version::stability_of(&pkg.version_normalized); + version::find_recommended_require_version( + &pkg.version, + &pkg.version_normalized, + stability, + ) + } + } +} |
