aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/mozart
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2026-05-03 12:25:45 +0900
committernsfisis <nsfisis@gmail.com>2026-05-03 12:25:45 +0900
commitab2772b8c85139df7d5e625ac5262d385e5ab4c0 (patch)
treeca2bbabecdb6068cbf646153d959c72edddec933 /crates/mozart
parent7badb54195131da9c3561c351138c0ba083e38e4 (diff)
downloadphp-mozart-ab2772b8c85139df7d5e625ac5262d385e5ab4c0.tar.gz
php-mozart-ab2772b8c85139df7d5e625ac5262d385e5ab4c0.tar.zst
php-mozart-ab2772b8c85139df7d5e625ac5262d385e5ab4c0.zip
fix(resolver): seed root package into pool as fixed entry
Composer's RootPackageRepository puts a clone of the root package into the pool as a fixed entry — its `require` / `require-dev` cleared, but its name, version, provides, and replaces preserved. That way a transitive `require` pointing back at the root resolves through the pool the same way any other reference would, and legal circular dependencies (root requires A, A requires root) work. Mozart had no such seed: the rule generator only knew about the root through the explicit root-require / root-provide / root-replace tables, so a transitive consumer requiring the root by name failed with no provider. Plumb root_version through ResolveRequest (RawPackageData gains a matching `Option<String>` field), build a fixed PoolPackageInput for the root with provides/replaces lifted from request.root_provide / root_replace, and skip the root by name when collecting the resolver's output so it doesn't leak into the lock file. Falls back to `1.0.0+no-version-set` (Composer's RootPackage::DEFAULT_PRETTY_VERSION) when the root composer.json omits `version`. Unblocks circular_dependency2, conflict_against_replaced_package_problem, and provider_conflicts installer fixtures. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Diffstat (limited to 'crates/mozart')
-rw-r--r--crates/mozart/src/commands/create_project.rs1
-rw-r--r--crates/mozart/src/commands/remove.rs4
-rw-r--r--crates/mozart/src/commands/require.rs3
-rw-r--r--crates/mozart/src/commands/update.rs2
-rw-r--r--crates/mozart/tests/installer.rs6
5 files changed, 13 insertions, 3 deletions
diff --git a/crates/mozart/src/commands/create_project.rs b/crates/mozart/src/commands/create_project.rs
index 139550a..eceafd0 100644
--- a/crates/mozart/src/commands/create_project.rs
+++ b/crates/mozart/src/commands/create_project.rs
@@ -409,6 +409,7 @@ pub async fn execute(
let request = ResolveRequest {
root_name: raw.name.clone(),
+ root_version: raw.version.clone(),
require,
require_dev,
include_dev: dev_mode,
diff --git a/crates/mozart/src/commands/remove.rs b/crates/mozart/src/commands/remove.rs
index df8bf2b..f11e9c3 100644
--- a/crates/mozart/src/commands/remove.rs
+++ b/crates/mozart/src/commands/remove.rs
@@ -243,6 +243,7 @@ pub async fn execute(
let request = ResolveRequest {
root_name: raw.name.clone(),
+ root_version: raw.version.clone(),
require,
require_dev,
include_dev: dev_mode,
@@ -513,6 +514,7 @@ async fn remove_unused(
let request = ResolveRequest {
root_name: raw.name.clone(),
+ root_version: raw.version.clone(),
require,
require_dev,
include_dev: dev_mode,
@@ -866,6 +868,7 @@ mod tests {
// Simulate initial install
let request = ResolveRequest {
root_name: String::new(),
+ root_version: None,
require: vec![("psr/log".to_string(), "^3.0".to_string())],
require_dev: vec![],
include_dev: false,
@@ -919,6 +922,7 @@ mod tests {
// Re-resolve with empty require
let request2 = ResolveRequest {
root_name: String::new(),
+ root_version: None,
require: vec![],
require_dev: vec![],
include_dev: false,
diff --git a/crates/mozart/src/commands/require.rs b/crates/mozart/src/commands/require.rs
index 69d7ea2..cac0dad 100644
--- a/crates/mozart/src/commands/require.rs
+++ b/crates/mozart/src/commands/require.rs
@@ -631,6 +631,7 @@ pub async fn execute(
let request = ResolveRequest {
root_name: raw.name.clone(),
+ root_version: raw.version.clone(),
require,
require_dev,
include_dev: dev_mode,
@@ -1031,6 +1032,7 @@ mod tests {
let request = ResolveRequest {
root_name: String::new(),
+ root_version: None,
require: vec![("psr/log".to_string(), "^3.0".to_string())],
require_dev: vec![],
include_dev: false,
@@ -1101,6 +1103,7 @@ mod tests {
let request = ResolveRequest {
root_name: String::new(),
+ root_version: None,
require: vec![("psr/log".to_string(), "^3.0".to_string())],
require_dev: vec![],
include_dev: false,
diff --git a/crates/mozart/src/commands/update.rs b/crates/mozart/src/commands/update.rs
index 0c25a9e..db9d616 100644
--- a/crates/mozart/src/commands/update.rs
+++ b/crates/mozart/src/commands/update.rs
@@ -883,6 +883,7 @@ pub async fn run(
let request = ResolveRequest {
root_name: composer_json.name.clone(),
+ root_version: composer_json.version.clone(),
require,
require_dev,
include_dev: dev_mode,
@@ -1993,6 +1994,7 @@ mod tests {
let request = ResolveRequest {
root_name: String::new(),
+ root_version: None,
require: vec![("monolog/monolog".to_string(), "^3.0".to_string())],
require_dev: vec![],
include_dev: false,
diff --git a/crates/mozart/tests/installer.rs b/crates/mozart/tests/installer.rs
index c680764..07e69d2 100644
--- a/crates/mozart/tests/installer.rs
+++ b/crates/mozart/tests/installer.rs
@@ -228,12 +228,12 @@ installer_fixture!(aliased_priority_conflicting, ignore);
installer_fixture!(aliases_with_require_dev, ignore);
installer_fixture!(broken_deps_do_not_replace, ignore);
installer_fixture!(circular_dependency, ignore);
-installer_fixture!(circular_dependency2, ignore);
+installer_fixture!(circular_dependency2);
installer_fixture!(circular_dependency_errors);
installer_fixture!(conflict_against_provided_by_dep_package_works);
installer_fixture!(conflict_against_provided_package_works);
installer_fixture!(conflict_against_replaced_by_dep_package_problem);
-installer_fixture!(conflict_against_replaced_package_problem, ignore);
+installer_fixture!(conflict_against_replaced_package_problem);
installer_fixture!(conflict_between_dependents);
installer_fixture!(conflict_between_root_and_dependent);
installer_fixture!(conflict_downgrade);
@@ -311,7 +311,7 @@ installer_fixture!(plugins_are_installed_first);
installer_fixture!(prefer_lowest_branches);
installer_fixture!(problems_reduce_versions);
installer_fixture!(provider_can_coexist_with_other_version_of_provided);
-installer_fixture!(provider_conflicts, ignore);
+installer_fixture!(provider_conflicts);
installer_fixture!(provider_conflicts2);
installer_fixture!(provider_conflicts3);
installer_fixture!(provider_dev_require_can_satisfy_require, ignore);