aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2026-02-22 15:45:33 +0900
committernsfisis <nsfisis@gmail.com>2026-02-22 15:45:33 +0900
commitd34f2ba41cb1d0111a4682f9d65628e06f46ff31 (patch)
treeeecb925ec7a33d5782eb08491db2aab6c4235fdc /crates
parent3bddf91f8fe386cc9d908ed498ea0b3235790904 (diff)
downloadphp-mozart-d34f2ba41cb1d0111a4682f9d65628e06f46ff31.tar.gz
php-mozart-d34f2ba41cb1d0111a4682f9d65628e06f46ff31.tar.zst
php-mozart-d34f2ba41cb1d0111a4682f9d65628e06f46ff31.zip
fix(resolver): replace __root__ with actual package name in error messages
Composer never shows the internal __root__ identifier to users. Add root_name field to ResolveRequest so the resolver can substitute the real package name (e.g. "laravel/laravel") in pubgrub error reports. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Diffstat (limited to 'crates')
-rw-r--r--crates/mozart-registry/src/lockfile.rs1
-rw-r--r--crates/mozart-registry/src/resolver.rs13
-rw-r--r--crates/mozart/src/commands/create_project.rs1
-rw-r--r--crates/mozart/src/commands/remove.rs3
-rw-r--r--crates/mozart/src/commands/require.rs3
-rw-r--r--crates/mozart/src/commands/update.rs2
6 files changed, 23 insertions, 0 deletions
diff --git a/crates/mozart-registry/src/lockfile.rs b/crates/mozart-registry/src/lockfile.rs
index 9064109..682dbb1 100644
--- a/crates/mozart-registry/src/lockfile.rs
+++ b/crates/mozart-registry/src/lockfile.rs
@@ -1019,6 +1019,7 @@ mod tests {
// Resolve monolog/monolog ^3.0
let resolve_request = ResolveRequest {
+ root_name: String::new(),
require: vec![("monolog/monolog".to_string(), "^3.0".to_string())],
require_dev: vec![],
include_dev: false,
diff --git a/crates/mozart-registry/src/resolver.rs b/crates/mozart-registry/src/resolver.rs
index 74acc52..61895eb 100644
--- a/crates/mozart-registry/src/resolver.rs
+++ b/crates/mozart-registry/src/resolver.rs
@@ -933,6 +933,9 @@ impl DependencyProvider for MozartProvider {
/// Input to the resolver.
pub struct ResolveRequest {
+ /// Root package name from composer.json "name" field (e.g. "laravel/laravel").
+ /// Used in error messages. Falls back to `__root__` if empty.
+ pub root_name: String,
/// Dependencies from composer.json "require" section.
pub require: Vec<(String, String)>,
/// Dependencies from composer.json "require-dev" section.
@@ -1026,6 +1029,7 @@ pub async fn resolve(request: &ResolveRequest) -> Result<Vec<ResolvedPackage>, R
let prefer_lowest = request.prefer_lowest;
let ignore_platform_reqs = request.ignore_platform_reqs;
let ignore_platform_req_list = request.ignore_platform_req_list.clone();
+ let root_name = request.root_name.clone();
// 2. Run pubgrub on a blocking thread (it is CPU-bound + uses block_on for I/O)
tokio::task::spawn_blocking(move || {
@@ -1078,6 +1082,14 @@ pub async fn resolve(request: &ResolveRequest) -> Result<Vec<ResolvedPackage>, R
Err(PubGrubError::NoSolution(mut derivation_tree)) => {
derivation_tree.collapse_no_versions();
let report = DefaultStringReporter::report(&derivation_tree);
+ // Replace the internal __root__ identifier with the actual
+ // package name so that error messages are user-friendly
+ // (matching Composer behaviour).
+ let report = if !root_name.is_empty() {
+ report.replace(PackageName::ROOT, &root_name)
+ } else {
+ report
+ };
Err(ResolveError::NoSolution(report))
}
Err(PubGrubError::ErrorRetrievingDependencies {
@@ -1920,6 +1932,7 @@ mod tests {
#[ignore]
async fn test_resolve_monolog_e2e() {
let request = ResolveRequest {
+ root_name: String::new(),
require: vec![("monolog/monolog".to_string(), "^3.0".to_string())],
require_dev: vec![],
include_dev: false,
diff --git a/crates/mozart/src/commands/create_project.rs b/crates/mozart/src/commands/create_project.rs
index d5a9b06..b4e3c3c 100644
--- a/crates/mozart/src/commands/create_project.rs
+++ b/crates/mozart/src/commands/create_project.rs
@@ -408,6 +408,7 @@ pub async fn execute(
.unwrap_or(false);
let request = ResolveRequest {
+ root_name: raw.name.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 5696f3e..eb8d501 100644
--- a/crates/mozart/src/commands/remove.rs
+++ b/crates/mozart/src/commands/remove.rs
@@ -262,6 +262,7 @@ pub async fn execute(
.unwrap_or(false);
let request = ResolveRequest {
+ root_name: raw.name.clone(),
require,
require_dev,
include_dev: dev_mode,
@@ -704,6 +705,7 @@ mod tests {
// Simulate initial install
let request = ResolveRequest {
+ root_name: String::new(),
require: vec![("psr/log".to_string(), "^3.0".to_string())],
require_dev: vec![],
include_dev: false,
@@ -738,6 +740,7 @@ mod tests {
// Re-resolve with empty require
let request2 = ResolveRequest {
+ root_name: String::new(),
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 13884b8..28b4e5e 100644
--- a/crates/mozart/src/commands/require.rs
+++ b/crates/mozart/src/commands/require.rs
@@ -583,6 +583,7 @@ pub async fn execute(
let prefer_stable = args.prefer_stable || composer_prefer_stable;
let request = ResolveRequest {
+ root_name: raw.name.clone(),
require,
require_dev,
include_dev: dev_mode,
@@ -924,6 +925,7 @@ mod tests {
let composer_json: RawPackageData = serde_json::from_str(composer_json_content).unwrap();
let request = ResolveRequest {
+ root_name: String::new(),
require: vec![("psr/log".to_string(), "^3.0".to_string())],
require_dev: vec![],
include_dev: false,
@@ -975,6 +977,7 @@ mod tests {
let raw: RawPackageData = serde_json::from_str(content).unwrap();
let request = ResolveRequest {
+ root_name: String::new(),
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 18e2c68..c782360 100644
--- a/crates/mozart/src/commands/update.rs
+++ b/crates/mozart/src/commands/update.rs
@@ -721,6 +721,7 @@ pub async fn execute(
let prefer_stable = args.prefer_stable || composer_prefer_stable;
let request = ResolveRequest {
+ root_name: composer_json.name.clone(),
require,
require_dev,
include_dev: dev_mode,
@@ -1671,6 +1672,7 @@ mod tests {
let composer_json: RawPackageData = serde_json::from_str(composer_json_content).unwrap();
let request = ResolveRequest {
+ root_name: String::new(),
require: vec![("monolog/monolog".to_string(), "^3.0".to_string())],
require_dev: vec![],
include_dev: false,