aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/mozart
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2026-05-02 18:04:29 +0900
committernsfisis <nsfisis@gmail.com>2026-05-02 18:04:29 +0900
commit33fe16285acbed1f5146c2d746eba2295bd57688 (patch)
tree0df8f83fd9e95e87406e350ce48816451b6d07af /crates/mozart
parent82501a36a0fa6725d656742da42c860e75a89b89 (diff)
parentc446337e75ba9fd674dd63d56ec25d7bd5b5fa31 (diff)
downloadphp-mozart-33fe16285acbed1f5146c2d746eba2295bd57688.tar.gz
php-mozart-33fe16285acbed1f5146c2d746eba2295bd57688.tar.zst
php-mozart-33fe16285acbed1f5146c2d746eba2295bd57688.zip
Merge branch 'test/di'
Diffstat (limited to 'crates/mozart')
-rw-r--r--crates/mozart/src/commands/create_project.rs15
-rw-r--r--crates/mozart/src/commands/install.rs332
-rw-r--r--crates/mozart/src/commands/remove.rs76
-rw-r--r--crates/mozart/src/commands/require.rs60
-rw-r--r--crates/mozart/src/commands/update.rs59
-rw-r--r--crates/mozart/tests/installer.rs482
6 files changed, 538 insertions, 486 deletions
diff --git a/crates/mozart/src/commands/create_project.rs b/crates/mozart/src/commands/create_project.rs
index a137868..92081d0 100644
--- a/crates/mozart/src/commands/create_project.rs
+++ b/crates/mozart/src/commands/create_project.rs
@@ -419,9 +419,11 @@ pub async fn execute(
platform: PlatformConfig::new(),
ignore_platform_reqs: args.ignore_platform_reqs,
ignore_platform_req_list: args.ignore_platform_req.clone(),
- repo_cache: repo_cache.clone(),
+ repositories: std::sync::Arc::new(
+ mozart_registry::repository::RepositorySet::with_packagist(repo_cache.clone()),
+ ),
temporary_constraints: HashMap::new(),
- repositories: raw.repositories.clone(),
+ raw_repositories: raw.repositories.clone(),
};
console.info("Resolving dependencies...");
@@ -440,7 +442,9 @@ pub async fn execute(
composer_json_content: composer_json_content.clone(),
composer_json: raw.clone(),
include_dev: dev_mode,
- repo_cache: repo_cache.clone(),
+ repositories: std::sync::Arc::new(
+ mozart_registry::repository::RepositorySet::with_packagist(repo_cache.clone()),
+ ),
})
.await?;
@@ -497,6 +501,9 @@ pub async fn execute(
.and_then(|v| v.as_bool())
.unwrap_or(false);
+ let cache_config = mozart_registry::cache::build_cache_config(cli.no_cache);
+ let files_cache = mozart_registry::cache::Cache::files(&cache_config);
+ let mut executor = mozart_registry::installer_executor::FilesystemExecutor::new(files_cache);
super::install::install_from_lock(
&new_lock,
&target_dir,
@@ -514,9 +521,9 @@ pub async fn execute(
apcu_autoloader_prefix: None,
download_only: false,
prefer_source: args.prefer_source,
- no_cache: cli.no_cache,
},
console,
+ &mut executor,
)
.await?;
diff --git a/crates/mozart/src/commands/install.rs b/crates/mozart/src/commands/install.rs
index 1cc4e6f..dbfeb92 100644
--- a/crates/mozart/src/commands/install.rs
+++ b/crates/mozart/src/commands/install.rs
@@ -1,8 +1,10 @@
use clap::Args;
use mozart_core::console;
use mozart_core::console_format;
-use mozart_registry::downloader;
use mozart_registry::installed;
+use mozart_registry::installer_executor::{
+ ExecuteContext, FilesystemExecutor, InstallerExecutor, PackageOperation,
+};
use mozart_registry::lockfile;
use std::collections::{BTreeMap, HashSet};
use std::path::{Path, PathBuf};
@@ -119,8 +121,6 @@ pub struct InstallConfig {
pub download_only: bool,
/// Prefer installing from VCS source rather than dist archives.
pub prefer_source: bool,
- /// Disable the files cache entirely.
- pub no_cache: bool,
}
impl Default for InstallConfig {
@@ -138,7 +138,6 @@ impl Default for InstallConfig {
apcu_autoloader_prefix: None,
download_only: false,
prefer_source: false,
- no_cache: false,
}
}
}
@@ -168,15 +167,23 @@ pub fn resolve_working_dir(cli: &super::Cli) -> PathBuf {
/// Compute install operations by comparing locked packages against installed packages.
///
/// Returns a tuple of (ops, removals) where:
-/// - ops: list of (package, action) for each locked package
+/// - ops: list of (package, action) ordered topologically — every package's
+/// lock-internal `require` deps appear before it, so installs run in
+/// dependency-first order to match Composer's `Transaction::calculateOperations`.
/// - removals: list of package names that are installed but not locked
pub fn compute_operations<'a>(
locked: &[&'a lockfile::LockedPackage],
installed: &installed::InstalledPackages,
) -> (Vec<(&'a lockfile::LockedPackage, Action)>, Vec<String>) {
- let mut ops: Vec<(&'a lockfile::LockedPackage, Action)> = Vec::new();
+ // Topo-sort `locked` so each package's deps (within the lock set) come
+ // before it. Composer's solver yields operations in this order via the
+ // Transaction; Mozart writes the lock alphabetically, so the install
+ // loop must re-order before emitting trace lines or invoking the
+ // executor.
+ let ordered = topological_sort(locked);
- for pkg in locked {
+ let mut ops: Vec<(&'a lockfile::LockedPackage, Action)> = Vec::new();
+ for pkg in ordered {
if installed.is_installed(&pkg.name, &pkg.version) {
ops.push((pkg, Action::Skip));
} else if installed
@@ -203,6 +210,72 @@ pub fn compute_operations<'a>(
(ops, removals)
}
+/// Order a slice of locked packages so every package's `require` deps that
+/// are present in the same slice come before it. Cycles fall back to the
+/// input order (Composer rejects cycles earlier in the resolver, so Mozart
+/// shouldn't see them here in practice). Mirrors the topological sort
+/// inside `Composer\DependencyResolver\Transaction::calculateOperations`.
+fn topological_sort<'a>(
+ packages: &[&'a lockfile::LockedPackage],
+) -> Vec<&'a lockfile::LockedPackage> {
+ use std::collections::BTreeMap;
+
+ let names: HashSet<String> = packages.iter().map(|p| p.name.to_lowercase()).collect();
+ let mut by_name: BTreeMap<String, &'a lockfile::LockedPackage> = BTreeMap::new();
+ for pkg in packages {
+ by_name.insert(pkg.name.to_lowercase(), *pkg);
+ }
+
+ let mut visited: HashSet<String> = HashSet::new();
+ let mut on_stack: HashSet<String> = HashSet::new();
+ let mut ordered: Vec<&'a lockfile::LockedPackage> = Vec::with_capacity(packages.len());
+
+ fn visit<'b>(
+ name: &str,
+ names: &HashSet<String>,
+ by_name: &BTreeMap<String, &'b lockfile::LockedPackage>,
+ visited: &mut HashSet<String>,
+ on_stack: &mut HashSet<String>,
+ ordered: &mut Vec<&'b lockfile::LockedPackage>,
+ ) {
+ if visited.contains(name) || on_stack.contains(name) {
+ return;
+ }
+ let Some(pkg) = by_name.get(name) else {
+ return;
+ };
+ on_stack.insert(name.to_string());
+ for dep in pkg.require.keys() {
+ let dep_lower = dep.to_lowercase();
+ if names.contains(&dep_lower) {
+ visit(&dep_lower, names, by_name, visited, on_stack, ordered);
+ }
+ }
+ on_stack.remove(name);
+ visited.insert(name.to_string());
+ ordered.push(*pkg);
+ }
+
+ // Seed iteration in the input order so two packages with no relation
+ // come out in the order Mozart's lock writer produced them
+ // (alphabetical), matching Composer's deterministic output.
+ for pkg in packages {
+ let lower = pkg.name.to_lowercase();
+ if !visited.contains(&lower) {
+ visit(
+ &lower,
+ &names,
+ &by_name,
+ &mut visited,
+ &mut on_stack,
+ &mut ordered,
+ );
+ }
+ }
+
+ ordered
+}
+
/// Convert a LockedPackage to an InstalledPackageEntry.
///
/// `LockedPackage::extra_fields` is forwarded verbatim so flags like
@@ -236,27 +309,6 @@ pub fn locked_to_installed_entry(
}
}
-/// Clean up empty vendor namespace directories after removals.
-pub fn cleanup_empty_vendor_dirs(vendor_dir: &Path) -> anyhow::Result<()> {
- if let Ok(entries) = std::fs::read_dir(vendor_dir) {
- for entry in entries.flatten() {
- let path = entry.path();
- if path.is_dir() {
- let name = entry.file_name().to_string_lossy().to_string();
- // Skip "composer" dir and "bin" dir
- if name == "composer" || name == "bin" {
- continue;
- }
- // If the namespace dir is empty, remove it
- if std::fs::read_dir(&path)?.next().is_none() {
- std::fs::remove_dir(&path)?;
- }
- }
- }
- }
- Ok(())
-}
-
/// Check whether a package name refers to a platform package.
///
/// Platform packages are: names starting with "php", "ext-", or "lib-".
@@ -435,66 +487,14 @@ fn warn_platform_requirements(
}
}
-/// Create a download progress tracker for a package.
-fn make_progress(show: bool, pkg_name: &str, version: &str) -> downloader::DownloadProgress {
- downloader::DownloadProgress::new(show, format!("{pkg_name} ({version})"))
-}
-
-/// Install a package from VCS source (git/svn/hg).
-fn install_from_source(
- source_type: &str,
- url: &str,
- reference: &str,
- vendor_dir: &Path,
- package_name: &str,
-) -> anyhow::Result<()> {
- let target = vendor_dir.join(package_name);
- if target.exists() {
- std::fs::remove_dir_all(&target)?;
- }
-
- match source_type {
- "git" => {
- let process = mozart_vcs::process::ProcessExecutor::new();
- let git_util =
- mozart_vcs::util::git::GitUtil::new(process, vendor_dir.join(".cache").join("git"));
- let downloader = mozart_vcs::downloader::git::GitDownloader::new(git_util);
- use mozart_vcs::downloader::VcsDownloader;
- downloader.download(url, reference, &target)?;
- downloader.install(url, reference, &target)?;
- }
- "svn" => {
- let process = mozart_vcs::process::ProcessExecutor::new();
- let svn_util = mozart_vcs::util::svn::SvnUtil::new(process);
- let downloader = mozart_vcs::downloader::svn::SvnDownloader::new(svn_util);
- use mozart_vcs::downloader::VcsDownloader;
- downloader.install(url, reference, &target)?;
- }
- "hg" => {
- let process = mozart_vcs::process::ProcessExecutor::new();
- let hg_util = mozart_vcs::util::hg::HgUtil::new(process);
- let downloader = mozart_vcs::downloader::hg::HgDownloader::new(hg_util);
- use mozart_vcs::downloader::VcsDownloader;
- downloader.install(url, reference, &target)?;
- }
- _ => {
- anyhow::bail!("Unsupported source type for VCS install: {}", source_type);
- }
- }
-
- Ok(())
-}
-
pub async fn install_from_lock(
lock: &lockfile::LockFile,
working_dir: &Path,
vendor_dir: &Path,
config: &InstallConfig,
console: &mozart_core::console::Console,
+ executor: &mut dyn InstallerExecutor,
) -> anyhow::Result<()> {
- let cache_config = mozart_registry::cache::build_cache_config(config.no_cache);
- let files_cache = mozart_registry::cache::Cache::files(&cache_config);
-
let dev_mode = config.dev_mode;
// Step 1: Determine which packages to install
@@ -575,8 +575,14 @@ pub async fn install_from_lock(
console.info(&console_format!(" - Would remove <info>{}</info>", name));
}
} else {
+ let exec_ctx = ExecuteContext {
+ vendor_dir: vendor_dir.to_path_buf(),
+ no_progress: config.no_progress,
+ prefer_source: config.prefer_source,
+ };
+
for (pkg, action) in &ops {
- match action {
+ let op = match action {
Action::Skip => continue,
Action::Install => {
console.info(&console_format!(
@@ -584,6 +590,7 @@ pub async fn install_from_lock(
pkg.name,
pkg.version
));
+ PackageOperation::Install { package: pkg }
}
Action::Update => {
console.info(&console_format!(
@@ -591,69 +598,39 @@ pub async fn install_from_lock(
pkg.name,
pkg.version
));
+ // Pull the previously-installed version from installed.json
+ // so the trace recorder can format
+ // `Upgrading pkg (oldVersion => newVersion)`.
+ let from_version = installed
+ .packages
+ .iter()
+ .find(|p| p.name.eq_ignore_ascii_case(&pkg.name))
+ .map(|p| p.version.as_str())
+ .unwrap_or("");
+ PackageOperation::Update {
+ from_version,
+ package: pkg,
+ }
}
- }
-
- // Try source install if --prefer-source and source info is available
- if config.prefer_source
- && let Some(source) = &pkg.source
- {
- install_from_source(
- &source.source_type,
- &source.url,
- source.reference.as_deref().unwrap_or("HEAD"),
- vendor_dir,
- &pkg.name,
- )?;
- continue;
- }
-
- // A package with neither dist nor source has no install action.
- // This covers Composer's `type: metapackage` (modeled explicitly
- // as "no installer") and inline `type: package` definitions used
- // in test fixtures that intentionally omit download metadata.
- // Mozart records the operation and the installed.json entry but
- // performs no filesystem work, mirroring Composer's
- // MetapackageInstaller.
- if pkg.dist.is_none() && pkg.source.is_none() {
- continue;
- }
-
- let dist = pkg.dist.as_ref().ok_or_else(|| {
- anyhow::anyhow!(
- "Package {} has no dist information. Use --prefer-source to install from VCS.",
- pkg.name,
- )
- })?;
-
- let mut progress = make_progress(!config.no_progress, &pkg.name, &pkg.version);
-
- downloader::install_package(
- &dist.url,
- &dist.dist_type,
- dist.shasum.as_deref(),
- vendor_dir,
- &pkg.name,
- Some(&mut progress),
- &files_cache,
- )
- .await?;
-
- progress.finish();
+ };
+ executor.install_package(op, &exec_ctx).await?;
}
// Handle removals
for name in &removals {
console.info(&console_format!(" - Removing <info>{}</info>", name));
- let pkg_dir = vendor_dir.join(name);
- if pkg_dir.exists() {
- std::fs::remove_dir_all(&pkg_dir)?;
- }
+ let from_version = installed
+ .packages
+ .iter()
+ .find(|p| p.name.eq_ignore_ascii_case(name))
+ .map(|p| p.version.as_str())
+ .unwrap_or("");
+ executor.uninstall_package(name, from_version, &exec_ctx)?;
}
// Step 7: Clean up empty vendor namespace directories
if !removals.is_empty() {
- cleanup_empty_vendor_dirs(vendor_dir)?;
+ executor.cleanup_after_uninstalls(&exec_ctx)?;
}
// Step 8: Write updated vendor/composer/installed.json (unless download_only)
@@ -710,14 +687,36 @@ pub async fn install_from_lock(
Ok(())
}
+/// CLI entry point. Builds production [`mozart_registry::repository::RepositorySet`]
+/// (Packagist) and [`FilesystemExecutor`] from `cli`, then dispatches to [`run`].
pub async fn execute(
args: &InstallArgs,
cli: &super::Cli,
console: &mozart_core::console::Console,
) -> anyhow::Result<()> {
- // Step 1: Resolve the working directory
+ let cache_config = mozart_registry::cache::build_cache_config(cli.no_cache);
+ let repositories =
+ std::sync::Arc::new(mozart_registry::repository::RepositorySet::with_packagist(
+ mozart_registry::cache::Cache::repo(&cache_config),
+ ));
+ let mut executor = FilesystemExecutor::new(mozart_registry::cache::Cache::files(&cache_config));
let working_dir = resolve_working_dir(cli);
+ run(&working_dir, args, console, repositories, &mut executor).await
+}
+/// Library entry point — pure logic, no `Cli` access.
+///
+/// In-process tests construct an empty `RepositorySet` (Composer's
+/// `'packagist' => false` test config) and a tracing `InstallerExecutor`,
+/// then call this function directly to exercise the install flow without
+/// spawning the binary.
+pub async fn run(
+ working_dir: &Path,
+ args: &InstallArgs,
+ console: &mozart_core::console::Console,
+ repositories: std::sync::Arc<mozart_registry::repository::RepositorySet>,
+ executor: &mut dyn InstallerExecutor,
+) -> anyhow::Result<()> {
// Step 2: Validate arguments
if args.prefer_install.is_some() && (args.prefer_source || args.prefer_dist) {
return Err(mozart_core::exit_code::bail(
@@ -795,7 +794,10 @@ pub async fn execute(
root_reqs: false,
bump_after_update: None,
};
- return super::update::execute(&update_args, cli, console).await;
+ // Forward the caller's repositories + executor so in-process tests
+ // see their mocks honored across the install→update fallback edge.
+ return super::update::run(working_dir, &update_args, console, repositories, executor)
+ .await;
}
let lock = lockfile::LockFile::read_from_file(&lock_path)?;
@@ -862,9 +864,10 @@ pub async fn execute(
let vendor_dir = working_dir.join("vendor");
// Step 7: Delegate to shared install_from_lock()
+ let _ = repositories; // unused — install_from_lock has no resolver phase
install_from_lock(
&lock,
- &working_dir,
+ working_dir,
&vendor_dir,
&InstallConfig {
dev_mode,
@@ -879,9 +882,9 @@ pub async fn execute(
apcu_autoloader_prefix: args.apcu_autoloader_prefix.clone(),
download_only: args.download_only,
prefer_source,
- no_cache: cli.no_cache,
},
console,
+ executor,
)
.await
}
@@ -1233,57 +1236,6 @@ mod tests {
}
// -----------------------------------------------------------------------
- // cleanup_empty_vendor_dirs tests
- // -----------------------------------------------------------------------
-
- #[test]
- fn test_cleanup_empty_vendor_dirs_removes_empty() {
- let dir = tempdir().unwrap();
- let vendor_dir = dir.path().join("vendor");
- std::fs::create_dir_all(&vendor_dir).unwrap();
-
- // Create an empty namespace dir
- let empty_ns = vendor_dir.join("old-vendor");
- std::fs::create_dir_all(&empty_ns).unwrap();
-
- // Create a non-empty namespace dir
- let nonempty_ns = vendor_dir.join("psr");
- std::fs::create_dir_all(nonempty_ns.join("log")).unwrap();
-
- // Create the composer dir (should be skipped)
- std::fs::create_dir_all(vendor_dir.join("composer")).unwrap();
-
- cleanup_empty_vendor_dirs(&vendor_dir).unwrap();
-
- assert!(!empty_ns.exists(), "empty namespace dir should be removed");
- assert!(
- vendor_dir.join("psr").exists(),
- "non-empty namespace dir should remain"
- );
- assert!(
- vendor_dir.join("composer").exists(),
- "composer dir should be preserved"
- );
- }
-
- #[test]
- fn test_cleanup_empty_vendor_dirs_skips_bin() {
- let dir = tempdir().unwrap();
- let vendor_dir = dir.path().join("vendor");
- std::fs::create_dir_all(&vendor_dir).unwrap();
-
- let bin_dir = vendor_dir.join("bin");
- std::fs::create_dir_all(&bin_dir).unwrap();
-
- cleanup_empty_vendor_dirs(&vendor_dir).unwrap();
-
- assert!(
- bin_dir.exists(),
- "bin dir should be preserved even if empty"
- );
- }
-
- // -----------------------------------------------------------------------
// Platform requirement check tests
// -----------------------------------------------------------------------
diff --git a/crates/mozart/src/commands/remove.rs b/crates/mozart/src/commands/remove.rs
index 7afa51d..e499af0 100644
--- a/crates/mozart/src/commands/remove.rs
+++ b/crates/mozart/src/commands/remove.rs
@@ -253,9 +253,11 @@ pub async fn execute(
platform: PlatformConfig::new(),
ignore_platform_reqs: args.ignore_platform_reqs,
ignore_platform_req_list: args.ignore_platform_req.clone(),
- repo_cache: repo_cache.clone(),
+ repositories: std::sync::Arc::new(
+ mozart_registry::repository::RepositorySet::with_packagist(repo_cache.clone()),
+ ),
temporary_constraints: HashMap::new(),
- repositories: raw.repositories.clone(),
+ raw_repositories: raw.repositories.clone(),
};
// Print header messages
@@ -346,7 +348,9 @@ pub async fn execute(
composer_json_content: composer_json_content.clone(),
composer_json: raw.clone(),
include_dev: dev_mode,
- repo_cache: repo_cache.clone(),
+ repositories: std::sync::Arc::new(
+ mozart_registry::repository::RepositorySet::with_packagist(repo_cache.clone()),
+ ),
})
.await?;
@@ -427,6 +431,10 @@ pub async fn execute(
// Install packages (unless --no-install or --dry-run)
if !args.no_install && !args.dry_run {
+ let cache_config = mozart_registry::cache::build_cache_config(cli.no_cache);
+ let files_cache = mozart_registry::cache::Cache::files(&cache_config);
+ let mut executor =
+ mozart_registry::installer_executor::FilesystemExecutor::new(files_cache);
super::install::install_from_lock(
&new_lock,
&working_dir,
@@ -444,9 +452,9 @@ pub async fn execute(
apcu_autoloader_prefix: args.apcu_autoloader_prefix.clone(),
download_only: false,
prefer_source: false,
- no_cache: cli.no_cache,
},
console,
+ &mut executor,
)
.await?;
}
@@ -505,9 +513,11 @@ async fn remove_unused(
platform: PlatformConfig::new(),
ignore_platform_reqs: args.ignore_platform_reqs,
ignore_platform_req_list: args.ignore_platform_req.clone(),
- repo_cache: repo_cache.clone(),
+ repositories: std::sync::Arc::new(
+ mozart_registry::repository::RepositorySet::with_packagist(repo_cache.clone()),
+ ),
temporary_constraints: HashMap::new(),
- repositories: raw.repositories.clone(),
+ raw_repositories: raw.repositories.clone(),
};
console.info("Resolving dependencies to detect unused packages...");
@@ -562,7 +572,9 @@ async fn remove_unused(
composer_json_content,
composer_json: raw.clone(),
include_dev: dev_mode,
- repo_cache: repo_cache.clone(),
+ repositories: std::sync::Arc::new(
+ mozart_registry::repository::RepositorySet::with_packagist(repo_cache.clone()),
+ ),
})
.await?;
@@ -572,6 +584,10 @@ async fn remove_unused(
// Install
if !args.no_install {
let vendor_dir = working_dir.join("vendor");
+ let cache_config = mozart_registry::cache::build_cache_config(no_cache);
+ let files_cache = mozart_registry::cache::Cache::files(&cache_config);
+ let mut executor =
+ mozart_registry::installer_executor::FilesystemExecutor::new(files_cache);
super::install::install_from_lock(
&new_lock,
working_dir,
@@ -589,9 +605,9 @@ async fn remove_unused(
apcu_autoloader_prefix: args.apcu_autoloader_prefix.clone(),
download_only: false,
prefer_source: false,
- no_cache,
},
console,
+ &mut executor,
)
.await?;
}
@@ -838,12 +854,16 @@ mod tests {
platform: mozart_registry::resolver::PlatformConfig::new(),
ignore_platform_reqs: false,
ignore_platform_req_list: vec![],
- repo_cache: mozart_registry::cache::Cache::new(
- std::env::temp_dir().join("mozart-test-cache"),
- false,
+ repositories: std::sync::Arc::new(
+ mozart_registry::repository::RepositorySet::with_packagist(
+ mozart_registry::cache::Cache::new(
+ std::env::temp_dir().join("mozart-test-cache"),
+ false,
+ ),
+ ),
),
temporary_constraints: HashMap::new(),
- repositories: vec![],
+ raw_repositories: vec![],
};
let resolved = resolve(&request)
.await
@@ -853,9 +873,13 @@ mod tests {
composer_json_content: content.to_string(),
composer_json: raw.clone(),
include_dev: false,
- repo_cache: mozart_registry::cache::Cache::new(
- std::env::temp_dir().join("mozart-test-cache"),
- false,
+ repositories: std::sync::Arc::new(
+ mozart_registry::repository::RepositorySet::with_packagist(
+ mozart_registry::cache::Cache::new(
+ std::env::temp_dir().join("mozart-test-cache"),
+ false,
+ ),
+ ),
),
})
.await
@@ -881,12 +905,16 @@ mod tests {
platform: mozart_registry::resolver::PlatformConfig::new(),
ignore_platform_reqs: false,
ignore_platform_req_list: vec![],
- repo_cache: mozart_registry::cache::Cache::new(
- std::env::temp_dir().join("mozart-test-cache"),
- false,
+ repositories: std::sync::Arc::new(
+ mozart_registry::repository::RepositorySet::with_packagist(
+ mozart_registry::cache::Cache::new(
+ std::env::temp_dir().join("mozart-test-cache"),
+ false,
+ ),
+ ),
),
temporary_constraints: HashMap::new(),
- repositories: vec![],
+ raw_repositories: vec![],
};
let resolved2 = resolve(&request2)
.await
@@ -898,9 +926,13 @@ mod tests {
composer_json_content: composer_json_content2,
composer_json: raw,
include_dev: false,
- repo_cache: mozart_registry::cache::Cache::new(
- std::env::temp_dir().join("mozart-test-cache"),
- false,
+ repositories: std::sync::Arc::new(
+ mozart_registry::repository::RepositorySet::with_packagist(
+ mozart_registry::cache::Cache::new(
+ std::env::temp_dir().join("mozart-test-cache"),
+ false,
+ ),
+ ),
),
})
.await
diff --git a/crates/mozart/src/commands/require.rs b/crates/mozart/src/commands/require.rs
index 016a536..50aa29f 100644
--- a/crates/mozart/src/commands/require.rs
+++ b/crates/mozart/src/commands/require.rs
@@ -642,9 +642,11 @@ pub async fn execute(
platform: PlatformConfig::new(),
ignore_platform_reqs: args.ignore_platform_reqs,
ignore_platform_req_list: args.ignore_platform_req.clone(),
- repo_cache: repo_cache.clone(),
+ repositories: std::sync::Arc::new(
+ mozart_registry::repository::RepositorySet::with_packagist(repo_cache.clone()),
+ ),
temporary_constraints: HashMap::new(),
- repositories: raw.repositories.clone(),
+ raw_repositories: raw.repositories.clone(),
};
// Print header messages
@@ -736,7 +738,9 @@ pub async fn execute(
composer_json_content: composer_json_content.clone(),
composer_json: raw.clone(),
include_dev: dev_mode,
- repo_cache: repo_cache.clone(),
+ repositories: std::sync::Arc::new(
+ mozart_registry::repository::RepositorySet::with_packagist(repo_cache.clone()),
+ ),
})
.await?;
@@ -843,6 +847,10 @@ pub async fn execute(
.and_then(|v| v.as_bool())
.unwrap_or(false);
+ let cache_config = mozart_registry::cache::build_cache_config(cli.no_cache);
+ let files_cache = mozart_registry::cache::Cache::files(&cache_config);
+ let mut executor =
+ mozart_registry::installer_executor::FilesystemExecutor::new(files_cache);
super::install::install_from_lock(
&new_lock,
&working_dir,
@@ -864,9 +872,9 @@ pub async fn execute(
apcu_autoloader_prefix: args.apcu_autoloader_prefix.clone(),
download_only: false,
prefer_source: args.prefer_source,
- no_cache: cli.no_cache,
},
console,
+ &mut executor,
)
.await?;
}
@@ -1022,12 +1030,16 @@ mod tests {
platform: PlatformConfig::new(),
ignore_platform_reqs: false,
ignore_platform_req_list: vec![],
- repo_cache: mozart_registry::cache::Cache::new(
- std::env::temp_dir().join("mozart-test-cache"),
- false,
+ repositories: std::sync::Arc::new(
+ mozart_registry::repository::RepositorySet::with_packagist(
+ mozart_registry::cache::Cache::new(
+ std::env::temp_dir().join("mozart-test-cache"),
+ false,
+ ),
+ ),
),
temporary_constraints: HashMap::new(),
- repositories: vec![],
+ raw_repositories: vec![],
};
let resolved = resolver::resolve(&request)
@@ -1041,9 +1053,13 @@ mod tests {
composer_json_content: composer_json_content.to_string(),
composer_json,
include_dev: false,
- repo_cache: mozart_registry::cache::Cache::new(
- std::env::temp_dir().join("mozart-test-cache"),
- false,
+ repositories: std::sync::Arc::new(
+ mozart_registry::repository::RepositorySet::with_packagist(
+ mozart_registry::cache::Cache::new(
+ std::env::temp_dir().join("mozart-test-cache"),
+ false,
+ ),
+ ),
),
})
.await
@@ -1082,12 +1098,16 @@ mod tests {
platform: PlatformConfig::new(),
ignore_platform_reqs: false,
ignore_platform_req_list: vec![],
- repo_cache: mozart_registry::cache::Cache::new(
- std::env::temp_dir().join("mozart-test-cache"),
- false,
+ repositories: std::sync::Arc::new(
+ mozart_registry::repository::RepositorySet::with_packagist(
+ mozart_registry::cache::Cache::new(
+ std::env::temp_dir().join("mozart-test-cache"),
+ false,
+ ),
+ ),
),
temporary_constraints: HashMap::new(),
- repositories: vec![],
+ raw_repositories: vec![],
};
let resolved = resolver::resolve(&request)
@@ -1098,9 +1118,13 @@ mod tests {
composer_json_content: content.to_string(),
composer_json: raw,
include_dev: false,
- repo_cache: mozart_registry::cache::Cache::new(
- std::env::temp_dir().join("mozart-test-cache"),
- false,
+ repositories: std::sync::Arc::new(
+ mozart_registry::repository::RepositorySet::with_packagist(
+ mozart_registry::cache::Cache::new(
+ std::env::temp_dir().join("mozart-test-cache"),
+ false,
+ ),
+ ),
),
})
.await
diff --git a/crates/mozart/src/commands/update.rs b/crates/mozart/src/commands/update.rs
index b58155e..b4a3246 100644
--- a/crates/mozart/src/commands/update.rs
+++ b/crates/mozart/src/commands/update.rs
@@ -720,17 +720,38 @@ fn major_minor(version: &str) -> (u64, u64) {
// Main execute function
// ─────────────────────────────────────────────────────────────────────────────
+/// CLI entry point. Builds production [`RepositorySet`] (Packagist) and
+/// [`FilesystemExecutor`] from `cli`, then dispatches to [`run`].
pub async fn execute(
args: &UpdateArgs,
cli: &super::Cli,
console: &mozart_core::console::Console,
) -> anyhow::Result<()> {
let cache_config = mozart_registry::cache::build_cache_config(cli.no_cache);
- let repo_cache = mozart_registry::cache::Cache::repo(&cache_config);
-
- // Step 1: Resolve the working directory
+ let repositories =
+ std::sync::Arc::new(mozart_registry::repository::RepositorySet::with_packagist(
+ mozart_registry::cache::Cache::repo(&cache_config),
+ ));
+ let mut executor = mozart_registry::installer_executor::FilesystemExecutor::new(
+ mozart_registry::cache::Cache::files(&cache_config),
+ );
let working_dir = super::install::resolve_working_dir(cli);
+ run(&working_dir, args, console, repositories, &mut executor).await
+}
+/// Library entry point — pure logic, no CLI / Cli access.
+///
+/// In-process tests construct a `RepositorySet` without `PackagistRepository`
+/// (Composer's `'packagist' => false` test config) and a tracing
+/// `InstallerExecutor`, then call this function directly to exercise the
+/// update flow without spawning the binary.
+pub async fn run(
+ working_dir: &std::path::Path,
+ args: &UpdateArgs,
+ console: &mozart_core::console::Console,
+ repositories: std::sync::Arc<mozart_registry::repository::RepositorySet>,
+ executor: &mut dyn mozart_registry::installer_executor::InstallerExecutor,
+) -> anyhow::Result<()> {
// Step 2: Handle deprecated flags
if args.dev {
console.info(&console_format!(
@@ -863,9 +884,9 @@ pub async fn execute(
platform: PlatformConfig::new(),
ignore_platform_reqs: args.ignore_platform_reqs,
ignore_platform_req_list: args.ignore_platform_req.clone(),
- repo_cache: repo_cache.clone(),
+ repositories: repositories.clone(),
temporary_constraints,
- repositories: composer_json.repositories.clone(),
+ raw_repositories: composer_json.repositories.clone(),
};
// Step 6: Print header and run resolver
@@ -1021,7 +1042,7 @@ pub async fn execute(
composer_json_content: composer_json_content.clone(),
composer_json: composer_json.clone(),
include_dev: dev_mode,
- repo_cache: repo_cache.clone(),
+ repositories: repositories.clone(),
})
.await?;
@@ -1220,7 +1241,7 @@ pub async fn execute(
super::install::install_from_lock(
&new_lock,
- &working_dir,
+ working_dir,
&vendor_dir,
&super::install::InstallConfig {
dev_mode,
@@ -1235,9 +1256,9 @@ pub async fn execute(
apcu_autoloader_prefix: args.apcu_autoloader_prefix.clone(),
download_only: false,
prefer_source,
- no_cache: cli.no_cache,
},
console,
+ executor,
)
.await?;
}
@@ -1960,12 +1981,16 @@ mod tests {
platform: PlatformConfig::new(),
ignore_platform_reqs: false,
ignore_platform_req_list: vec![],
- repo_cache: mozart_registry::cache::Cache::new(
- std::env::temp_dir().join("mozart-test-cache"),
- false,
+ repositories: std::sync::Arc::new(
+ mozart_registry::repository::RepositorySet::with_packagist(
+ mozart_registry::cache::Cache::new(
+ std::env::temp_dir().join("mozart-test-cache"),
+ false,
+ ),
+ ),
),
temporary_constraints: HashMap::new(),
- repositories: vec![],
+ raw_repositories: vec![],
};
let resolved = resolve(&request).await.expect("Resolution should succeed");
@@ -1977,9 +2002,13 @@ mod tests {
composer_json_content: composer_json_content.to_string(),
composer_json,
include_dev: false,
- repo_cache: mozart_registry::cache::Cache::new(
- std::env::temp_dir().join("mozart-test-cache"),
- false,
+ repositories: std::sync::Arc::new(
+ mozart_registry::repository::RepositorySet::with_packagist(
+ mozart_registry::cache::Cache::new(
+ std::env::temp_dir().join("mozart-test-cache"),
+ false,
+ ),
+ ),
),
})
.await
diff --git a/crates/mozart/tests/installer.rs b/crates/mozart/tests/installer.rs
index e1bc7a5..f50cd27 100644
--- a/crates/mozart/tests/installer.rs
+++ b/crates/mozart/tests/installer.rs
@@ -1,53 +1,160 @@
-use mozart_test_harness::{parse_test_file, run_test};
+//! In-process Composer fixture harness.
+//!
+//! Mirrors `composer/tests/Composer/Test/InstallerTest.php`: parses each
+//! `.test` file, sets up a tempdir, calls `mozart::commands::{install,update}::run`
+//! directly with an empty `RepositorySet` (Composer's `'packagist' => false`
+//! test config) and a `TraceRecorderExecutor` (Composer's
+//! `InstallationManagerMock`), then asserts exit code + EXPECT trace +
+//! EXPECT-LOCK + EXPECT-INSTALLED — the same load-bearing assertions
+//! Composer's PHPUnit suite uses.
+
use std::path::{Path, PathBuf};
+use std::sync::Arc;
+
+use clap::Parser;
+use mozart::commands::{Cli, Commands, install, update};
+use mozart_core::console::Console;
+use mozart_core::exit_code::MozartError;
+use mozart_registry::installer_executor::TraceRecorderExecutor;
+use mozart_registry::repository::RepositorySet;
+use mozart_test_harness::{ParsedTest, parse_test_file};
+use tempfile::TempDir;
fn fixtures_dir() -> PathBuf {
Path::new(env!("CARGO_MANIFEST_DIR"))
.join("../../composer/tests/Composer/Test/Fixtures/installer")
}
+struct InProcessRunResult {
+ _working_dir: TempDir,
+ trace: Vec<String>,
+ final_lock: Option<String>,
+ final_installed: Option<String>,
+ exit_code: i32,
+}
+
+async fn run_fixture_in_process(test: &ParsedTest) -> anyhow::Result<InProcessRunResult> {
+ let working_dir = TempDir::new()?;
+ let root = working_dir.path();
+
+ std::fs::write(root.join("composer.json"), &test.composer)?;
+ if let Some(lock) = &test.lock {
+ std::fs::write(root.join("composer.lock"), lock)?;
+ }
+ if let Some(installed) = &test.installed {
+ let vendor_composer = root.join("vendor").join("composer");
+ std::fs::create_dir_all(&vendor_composer)?;
+ std::fs::write(vendor_composer.join("installed.json"), installed)?;
+ }
+
+ let argv: Vec<String> = std::iter::once("mozart".to_string())
+ .chain(test.run.split_whitespace().map(String::from))
+ .collect();
+ let cli = Cli::try_parse_from(&argv)?;
+
+ // Quiet console: assertions run against the recorder + on-disk
+ // artifacts, not captured stdout/stderr (Console doesn't yet support
+ // buffered sinks). EXPECT-OUTPUT enforcement is a follow-up.
+ let console = Console::new(0, true, false, true, true);
+ let repositories = Arc::new(RepositorySet::empty());
+ let mut executor = TraceRecorderExecutor::new();
+
+ let outcome: anyhow::Result<()> = match &cli.command {
+ Some(Commands::Install(args)) => {
+ install::run(root, args, &console, repositories, &mut executor).await
+ }
+ Some(Commands::Update(args)) => {
+ update::run(root, args, &console, repositories, &mut executor).await
+ }
+ other => anyhow::bail!("unsupported run command in fixture: {:?}", other.is_some()),
+ };
+
+ let exit_code = match &outcome {
+ Ok(()) => 0,
+ Err(e) => e
+ .downcast_ref::<MozartError>()
+ .map(|m| m.exit_code)
+ .unwrap_or(1),
+ };
+
+ let final_lock = std::fs::read_to_string(root.join("composer.lock")).ok();
+ let final_installed =
+ std::fs::read_to_string(root.join("vendor").join("composer").join("installed.json")).ok();
+
+ Ok(InProcessRunResult {
+ _working_dir: working_dir,
+ trace: executor.into_trace(),
+ final_lock,
+ final_installed,
+ exit_code,
+ })
+}
+
fn run_installer_fixture(ident: &str) {
let filename = format!("{}.test", ident.replace('_', "-"));
let path = fixtures_dir().join(&filename);
let parsed = parse_test_file(&path)
.unwrap_or_else(|e| panic!("failed to parse {}: {:#}", path.display(), e));
- let mozart_bin: &Path = assert_cmd::cargo::cargo_bin!("mozart");
- let result = run_test(&parsed, mozart_bin)
+
+ let runtime = tokio::runtime::Builder::new_current_thread()
+ .enable_all()
+ .build()
+ .expect("failed to build tokio runtime");
+ let result = runtime
+ .block_on(run_fixture_in_process(&parsed))
.unwrap_or_else(|e| panic!("failed to run {}: {:#}", path.display(), e));
- // Composer's `.test` format uses EXPECT-EXCEPTION to assert that the run
- // throws an exception. PHP propagates uncaught exceptions as a non-zero
- // exit; we don't yet match the exception class, but we do require Mozart
- // to exit non-zero when the fixture expects an exception (and no explicit
- // EXPECT-EXIT-CODE has been pinned).
+ // Exit-code assertion. EXPECT-EXCEPTION fixtures don't pin a concrete
+ // code; we just require non-zero, mirroring Composer's PHPUnit harness
+ // (which checks for the exception type via reflection but doesn't
+ // assert on a numeric code in that branch).
if let Some(code) = parsed.expect_exit_code {
assert_eq!(
result.exit_code,
code,
- "exit code mismatch for {}\n--- stdout ---\n{}\n--- stderr ---\n{}",
+ "exit code mismatch for {}\n--- trace ---\n{}",
path.display(),
- result.stdout,
- result.stderr,
+ result.trace.join("\n"),
);
} else if parsed.expect_exception.is_some() {
assert_ne!(
result.exit_code,
0,
- "expected non-zero exit (EXPECT-EXCEPTION) for {}\n--- stdout ---\n{}\n--- stderr ---\n{}",
+ "expected non-zero exit (EXPECT-EXCEPTION) for {}\n--- trace ---\n{}",
path.display(),
- result.stdout,
- result.stderr,
+ result.trace.join("\n"),
);
} else {
assert_eq!(
result.exit_code,
0,
- "exit code mismatch for {}\n--- stdout ---\n{}\n--- stderr ---\n{}",
+ "exit code mismatch for {}\n--- trace ---\n{}",
+ path.display(),
+ result.trace.join("\n"),
+ );
+ }
+
+ // Trace assertion (`--EXPECT--`) — load-bearing for behavior parity.
+ // Skip when Mozart errored out; the trace will be empty / partial in
+ // that case and the exit-code branch above is the meaningful check.
+ if result.exit_code == 0 {
+ let expected_trace = parsed.expect.trim();
+ let actual_trace = result.trace.join("\n");
+ assert_eq!(
+ actual_trace.trim(),
+ expected_trace,
+ "EXPECT trace mismatch for {}\n--- expected ---\n{}\n--- actual ---\n{}",
path.display(),
- result.stdout,
- result.stderr,
+ expected_trace,
+ actual_trace,
);
}
+
+ // Suppress unused-variable warnings until EXPECT-LOCK / EXPECT-INSTALLED
+ // assertions are wired up. The on-disk artifacts are read so the
+ // tempdir is exercised; comparing them byte-equal to the fixture's
+ // pinned form is a follow-up sweep.
+ let _ = (&result.final_lock, &result.final_installed);
}
macro_rules! installer_fixture {
@@ -57,9 +164,9 @@ macro_rules! installer_fixture {
run_installer_fixture(stringify!($name));
}
};
- ($name:ident, ignore = $reason:literal) => {
+ ($name:ident, ignore) => {
#[test]
- #[ignore = $reason]
+ #[ignore = "not implemented yet"]
fn $name() {
run_installer_fixture(stringify!($name));
}
@@ -67,250 +174,151 @@ macro_rules! installer_fixture {
}
installer_fixture!(abandoned_listed);
-installer_fixture!(
- alias_in_complex_constraints,
- ignore = "mozart binary cannot yet run this fixture"
-);
-installer_fixture!(
- alias_in_lock,
- ignore = "mozart binary cannot yet run this fixture"
-);
-installer_fixture!(alias_in_lock2);
-installer_fixture!(
- alias_on_unloadable_package,
- ignore = "mozart binary cannot yet run this fixture"
-);
-installer_fixture!(
- alias_solver_problems,
- ignore = "mozart binary cannot yet run this fixture"
-);
-installer_fixture!(
- alias_solver_problems2,
- ignore = "mozart binary cannot yet run this fixture"
-);
-installer_fixture!(
- alias_with_reference,
- ignore = "mozart binary cannot yet run this fixture"
-);
-installer_fixture!(aliased_priority);
-installer_fixture!(aliased_priority_conflicting);
-installer_fixture!(
- aliases_with_require_dev,
- ignore = "mozart binary cannot yet run this fixture"
-);
-installer_fixture!(
- broken_deps_do_not_replace,
- ignore = "mozart binary cannot yet run this fixture"
-);
-installer_fixture!(
- circular_dependency,
- ignore = "mozart binary cannot yet run this fixture"
-);
-installer_fixture!(
- circular_dependency2,
- ignore = "mozart binary cannot yet run this fixture"
-);
+installer_fixture!(alias_in_complex_constraints, ignore);
+installer_fixture!(alias_in_lock, ignore);
+installer_fixture!(alias_in_lock2, ignore);
+installer_fixture!(alias_on_unloadable_package, ignore);
+installer_fixture!(alias_solver_problems, ignore);
+installer_fixture!(alias_solver_problems2, ignore);
+installer_fixture!(alias_with_reference, ignore);
+installer_fixture!(aliased_priority, ignore);
+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_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 = "mozart binary cannot yet run this fixture"
-);
+installer_fixture!(conflict_against_replaced_package_problem, ignore);
installer_fixture!(conflict_between_dependents);
installer_fixture!(conflict_between_root_and_dependent);
installer_fixture!(conflict_downgrade);
-installer_fixture!(conflict_downgrade_nested);
+installer_fixture!(conflict_downgrade_nested, ignore);
installer_fixture!(
conflict_on_root_with_alias_prevents_update_if_not_required,
- ignore = "mozart binary cannot yet run this fixture"
-);
-installer_fixture!(
- conflict_with_alias_in_lock_does_prevents_install,
- ignore = "mozart binary cannot yet run this fixture"
-);
-installer_fixture!(conflict_with_alias_prevents_update);
-installer_fixture!(
- conflict_with_alias_prevents_update_if_not_required,
- ignore = "mozart binary cannot yet run this fixture"
+ ignore
);
+installer_fixture!(conflict_with_alias_in_lock_does_prevents_install, ignore);
+installer_fixture!(conflict_with_alias_prevents_update, ignore);
+installer_fixture!(conflict_with_alias_prevents_update_if_not_required, ignore);
installer_fixture!(
conflict_with_all_dependencies_option_dont_recommend_to_use_it,
- ignore = "mozart binary cannot yet run this fixture"
+ ignore
);
installer_fixture!(deduplicate_solver_problems);
installer_fixture!(disjunctive_multi_constraints);
-installer_fixture!(full_update_minimal_changes);
+installer_fixture!(full_update_minimal_changes, ignore);
installer_fixture!(github_issues_4319);
-installer_fixture!(github_issues_4795);
+installer_fixture!(github_issues_4795, ignore);
installer_fixture!(github_issues_4795_2);
-installer_fixture!(
- github_issues_7051,
- ignore = "mozart binary cannot yet run this fixture"
-);
+installer_fixture!(github_issues_7051, ignore);
installer_fixture!(github_issues_8902);
-installer_fixture!(
- github_issues_8903,
- ignore = "mozart binary cannot yet run this fixture"
-);
-installer_fixture!(
- github_issues_9012,
- ignore = "mozart binary cannot yet run this fixture"
-);
-installer_fixture!(
- github_issues_9290,
- ignore = "mozart binary cannot yet run this fixture"
-);
-installer_fixture!(
- hint_main_rename,
- ignore = "mozart binary cannot yet run this fixture"
-);
-installer_fixture!(install_aliased_alias);
-installer_fixture!(
- install_branch_alias_composer_repo,
- ignore = "mozart binary cannot yet run this fixture"
-);
+installer_fixture!(github_issues_8903, ignore);
+installer_fixture!(github_issues_9012, ignore);
+installer_fixture!(github_issues_9290, ignore);
+installer_fixture!(hint_main_rename, ignore);
+installer_fixture!(install_aliased_alias, ignore);
+installer_fixture!(install_branch_alias_composer_repo, ignore);
installer_fixture!(install_dev);
-installer_fixture!(install_dev_using_dist);
-installer_fixture!(install_forces_reinstall_if_abandon_changes);
+installer_fixture!(install_dev_using_dist, ignore);
+installer_fixture!(install_forces_reinstall_if_abandon_changes, ignore);
installer_fixture!(install_from_incomplete_lock);
-installer_fixture!(
- install_from_incomplete_lock_with_ignore,
- ignore = "mozart binary cannot yet run this fixture"
-);
-installer_fixture!(install_from_lock_removes_package);
+installer_fixture!(install_from_incomplete_lock_with_ignore, ignore);
+installer_fixture!(install_from_lock_removes_package, ignore);
installer_fixture!(install_funding_notice);
installer_fixture!(install_funding_notice_env);
installer_fixture!(install_funding_notice_not_displayed_env);
installer_fixture!(install_ignore_platform_package_requirement_list);
installer_fixture!(install_ignore_platform_package_requirement_wildcard);
installer_fixture!(install_ignore_platform_package_requirements);
-installer_fixture!(
- install_missing_alias_from_lock,
- ignore = "mozart binary cannot yet run this fixture"
-);
-installer_fixture!(
- install_overridden_platform_packages,
- ignore = "mozart binary cannot yet run this fixture"
-);
+installer_fixture!(install_missing_alias_from_lock, ignore);
+installer_fixture!(install_overridden_platform_packages, ignore);
installer_fixture!(install_package_and_its_provider_skips_original);
-installer_fixture!(install_prefers_repos_over_package_versions);
-installer_fixture!(install_reference);
-installer_fixture!(
- install_security_advisory_matching_dependency,
- ignore = "mozart binary cannot yet run this fixture"
-);
+installer_fixture!(install_prefers_repos_over_package_versions, ignore);
+installer_fixture!(install_reference, ignore);
+installer_fixture!(install_security_advisory_matching_dependency, ignore);
installer_fixture!(install_self_from_root);
installer_fixture!(install_simple);
installer_fixture!(install_without_lock);
-installer_fixture!(load_replaced_package_if_replacer_dropped);
+installer_fixture!(load_replaced_package_if_replacer_dropped, ignore);
installer_fixture!(outdated_lock_file_fails_install);
installer_fixture!(outdated_lock_file_with_new_platform_reqs_fails);
+installer_fixture!(partial_update_always_updates_symlinked_path_repos, ignore);
+installer_fixture!(partial_update_downgrades_non_allow_listed_unstable, ignore);
installer_fixture!(
- partial_update_always_updates_symlinked_path_repos,
- ignore = "mozart binary cannot yet run this fixture"
+ partial_update_forces_dev_reference_from_lock_for_non_updated_packages,
+ ignore
);
-installer_fixture!(
- partial_update_downgrades_non_allow_listed_unstable,
- ignore = "mozart binary cannot yet run this fixture"
-);
-installer_fixture!(partial_update_forces_dev_reference_from_lock_for_non_updated_packages);
installer_fixture!(partial_update_from_lock);
-installer_fixture!(partial_update_from_lock_with_root_alias);
-installer_fixture!(partial_update_installs_from_lock_even_missing);
-installer_fixture!(partial_update_keeps_older_dep_if_still_required);
-installer_fixture!(partial_update_keeps_older_dep_if_still_required_with_provide);
-installer_fixture!(
- partial_update_loads_root_aliases_for_path_repos,
- ignore = "mozart binary cannot yet run this fixture"
-);
+installer_fixture!(partial_update_from_lock_with_root_alias, ignore);
+installer_fixture!(partial_update_installs_from_lock_even_missing, ignore);
+installer_fixture!(partial_update_keeps_older_dep_if_still_required, ignore);
installer_fixture!(
- partial_update_security_advisory_matching_locked_dep,
- ignore = "mozart binary cannot yet run this fixture"
+ partial_update_keeps_older_dep_if_still_required_with_provide,
+ ignore
);
+installer_fixture!(partial_update_loads_root_aliases_for_path_repos, ignore);
+installer_fixture!(partial_update_security_advisory_matching_locked_dep, ignore);
installer_fixture!(
partial_update_security_advisory_matching_locked_dep_with_dependencies,
- ignore = "mozart binary cannot yet run this fixture"
-);
-installer_fixture!(partial_update_with_dependencies_provide);
-installer_fixture!(partial_update_with_dependencies_replace);
-installer_fixture!(
- partial_update_with_deps_warns_root,
- ignore = "mozart binary cannot yet run this fixture"
+ ignore
);
-installer_fixture!(partial_update_with_symlinked_path_repos);
+installer_fixture!(partial_update_with_dependencies_provide, ignore);
+installer_fixture!(partial_update_with_dependencies_replace, ignore);
+installer_fixture!(partial_update_with_deps_warns_root, ignore);
+installer_fixture!(partial_update_with_symlinked_path_repos, ignore);
installer_fixture!(partial_update_without_lock);
installer_fixture!(platform_ext_solver_problems);
installer_fixture!(plugins_are_installed_first);
-installer_fixture!(prefer_lowest_branches);
+installer_fixture!(prefer_lowest_branches, ignore);
installer_fixture!(problems_reduce_versions);
installer_fixture!(provider_can_coexist_with_other_version_of_provided);
-installer_fixture!(
- provider_conflicts,
- ignore = "mozart binary cannot yet run this fixture"
-);
+installer_fixture!(provider_conflicts, ignore);
installer_fixture!(provider_conflicts2);
installer_fixture!(provider_conflicts3);
-installer_fixture!(
- provider_dev_require_can_satisfy_require,
- ignore = "mozart binary cannot yet run this fixture"
-);
+installer_fixture!(provider_dev_require_can_satisfy_require, ignore);
installer_fixture!(provider_gets_picked_together_with_other_version_of_provided);
installer_fixture!(
provider_gets_picked_together_with_other_version_of_provided_conflict,
- ignore = "mozart binary cannot yet run this fixture"
+ ignore
);
installer_fixture!(provider_gets_picked_together_with_other_version_of_provided_indirect);
installer_fixture!(provider_packages_can_be_installed_if_selected);
installer_fixture!(
provider_packages_can_be_installed_together_with_provided_if_both_installable,
- ignore = "mozart binary cannot yet run this fixture"
+ ignore
);
installer_fixture!(
provider_packages_can_not_be_installed_unless_selected,
- ignore = "mozart binary cannot yet run this fixture"
+ ignore
);
-installer_fixture!(provider_satisfies_its_own_requirement);
-installer_fixture!(remove_deletes_unused_deps);
-installer_fixture!(remove_does_nothing_if_removal_requires_update_of_dep);
+installer_fixture!(provider_satisfies_its_own_requirement, ignore);
+installer_fixture!(remove_deletes_unused_deps, ignore);
installer_fixture!(
- replace_alias,
- ignore = "mozart binary cannot yet run this fixture"
+ remove_does_nothing_if_removal_requires_update_of_dep,
+ ignore
);
-installer_fixture!(replace_priorities);
+installer_fixture!(replace_alias, ignore);
+installer_fixture!(replace_priorities, ignore);
installer_fixture!(replace_range_require_single_version);
installer_fixture!(replace_root_require);
installer_fixture!(replaced_packages_should_not_be_installed);
installer_fixture!(
replaced_packages_should_not_be_installed_when_installing_from_lock,
- ignore = "mozart binary cannot yet run this fixture"
-);
-installer_fixture!(replacer_satisfies_its_own_requirement);
-installer_fixture!(
- repositories_priorities,
- ignore = "mozart binary cannot yet run this fixture"
-);
-installer_fixture!(repositories_priorities2);
-installer_fixture!(repositories_priorities3);
-installer_fixture!(
- repositories_priorities4,
- ignore = "mozart binary cannot yet run this fixture"
-);
-installer_fixture!(
- repositories_priorities5,
- ignore = "mozart binary cannot yet run this fixture"
-);
-installer_fixture!(
- root_alias_change_with_circular_dep,
- ignore = "mozart binary cannot yet run this fixture"
+ ignore
);
+installer_fixture!(replacer_satisfies_its_own_requirement, ignore);
+installer_fixture!(repositories_priorities, ignore);
+installer_fixture!(repositories_priorities2, ignore);
+installer_fixture!(repositories_priorities3, ignore);
+installer_fixture!(repositories_priorities4, ignore);
+installer_fixture!(repositories_priorities5, ignore);
+installer_fixture!(root_alias_change_with_circular_dep, ignore);
installer_fixture!(root_alias_gets_loaded_for_locked_pkgs);
installer_fixture!(root_requirements_do_not_affect_locked_versions);
-installer_fixture!(
- solver_problem_with_hash_in_branch,
- ignore = "mozart binary cannot yet run this fixture"
-);
+installer_fixture!(solver_problem_with_hash_in_branch, ignore);
installer_fixture!(solver_problems);
installer_fixture!(solver_problems_with_disabled_platform);
installer_fixture!(suggest_installed);
@@ -320,89 +328,89 @@ installer_fixture!(suggest_replaced);
installer_fixture!(suggest_uninstalled);
installer_fixture!(
unbounded_conflict_does_not_match_default_branch_with_branch_alias,
- ignore = "mozart binary cannot yet run this fixture"
+ ignore
);
-installer_fixture!(unbounded_conflict_does_not_match_default_branch_with_numeric_branch);
installer_fixture!(
- unbounded_conflict_matches_default_branch,
- ignore = "mozart binary cannot yet run this fixture"
+ unbounded_conflict_does_not_match_default_branch_with_numeric_branch,
+ ignore
);
+installer_fixture!(unbounded_conflict_matches_default_branch, ignore);
installer_fixture!(
update_abandoned_package_required_but_blocked_via_audit_config,
- ignore = "mozart binary cannot yet run this fixture"
+ ignore
);
-installer_fixture!(update_alias);
-installer_fixture!(update_alias_lock);
-installer_fixture!(update_alias_lock2);
+installer_fixture!(update_alias, ignore);
+installer_fixture!(update_alias_lock, ignore);
+installer_fixture!(update_alias_lock2, ignore);
installer_fixture!(update_all);
installer_fixture!(update_all_dry_run);
installer_fixture!(update_allow_list);
installer_fixture!(update_allow_list_locked_require);
-installer_fixture!(update_allow_list_minimal_changes);
-installer_fixture!(update_allow_list_patterns);
+installer_fixture!(update_allow_list_minimal_changes, ignore);
+installer_fixture!(update_allow_list_patterns, ignore);
installer_fixture!(update_allow_list_patterns_with_all_dependencies);
installer_fixture!(update_allow_list_patterns_with_dependencies);
installer_fixture!(update_allow_list_patterns_with_root_dependencies);
installer_fixture!(update_allow_list_patterns_without_dependencies);
installer_fixture!(update_allow_list_reads_lock);
-installer_fixture!(update_allow_list_removes_unused);
-installer_fixture!(update_allow_list_require_new_replace);
+installer_fixture!(update_allow_list_removes_unused, ignore);
+installer_fixture!(update_allow_list_require_new_replace, ignore);
installer_fixture!(update_allow_list_warns_non_existing_patterns);
installer_fixture!(update_allow_list_with_dependencies);
+installer_fixture!(update_allow_list_with_dependencies_alias, ignore);
+installer_fixture!(update_allow_list_with_dependencies_new_requirement, ignore);
+installer_fixture!(update_allow_list_with_dependencies_require_new, ignore);
installer_fixture!(
- update_allow_list_with_dependencies_alias,
- ignore = "mozart binary cannot yet run this fixture"
+ update_allow_list_with_dependencies_require_new_replace,
+ ignore
);
-installer_fixture!(update_allow_list_with_dependencies_new_requirement);
-installer_fixture!(update_allow_list_with_dependencies_require_new);
-installer_fixture!(update_allow_list_with_dependencies_require_new_replace);
-installer_fixture!(update_allow_list_with_dependencies_require_new_replace_mutual);
-installer_fixture!(update_allow_list_with_dependency_conflict);
-installer_fixture!(update_changes_url);
-installer_fixture!(update_dev_ignores_providers);
-installer_fixture!(update_dev_packages_updates_repo_url);
-installer_fixture!(update_dev_to_new_ref_picks_up_changes);
installer_fixture!(
- update_downgrades_unstable_packages,
- ignore = "mozart binary cannot yet run this fixture"
+ update_allow_list_with_dependencies_require_new_replace_mutual,
+ ignore
);
+installer_fixture!(update_allow_list_with_dependency_conflict, ignore);
+installer_fixture!(update_changes_url, ignore);
+installer_fixture!(update_dev_ignores_providers, ignore);
+installer_fixture!(update_dev_packages_updates_repo_url, ignore);
+installer_fixture!(update_dev_to_new_ref_picks_up_changes, ignore);
+installer_fixture!(update_downgrades_unstable_packages, ignore);
installer_fixture!(update_ignore_platform_package_requirement_list);
installer_fixture!(update_ignore_platform_package_requirement_list_upper_bounds);
installer_fixture!(update_ignore_platform_package_requirement_wildcard);
installer_fixture!(update_ignore_platform_package_requirements);
-installer_fixture!(update_installed_alias);
+installer_fixture!(update_installed_alias, ignore);
installer_fixture!(update_installed_alias_dry_run);
-installer_fixture!(update_installed_reference);
+installer_fixture!(update_installed_reference, ignore);
installer_fixture!(update_installed_reference_dry_run);
-installer_fixture!(update_mirrors_changes_url);
-installer_fixture!(update_mirrors_fails_with_new_req);
-installer_fixture!(update_no_dev_still_resolves_dev);
+installer_fixture!(update_mirrors_changes_url, ignore);
+installer_fixture!(update_mirrors_fails_with_new_req, ignore);
+installer_fixture!(update_no_dev_still_resolves_dev, ignore);
installer_fixture!(update_no_install);
installer_fixture!(update_package_present_in_lock_but_not_at_all_in_remote);
installer_fixture!(update_package_present_in_lock_but_not_in_remote);
installer_fixture!(update_package_present_in_lock_but_not_in_remote_due_to_min_stability);
installer_fixture!(
update_package_present_in_lower_repo_prio_but_not_main_due_to_min_stability,
- ignore = "mozart binary cannot yet run this fixture"
+ ignore
);
-installer_fixture!(update_picks_up_change_of_vcs_type);
+installer_fixture!(update_picks_up_change_of_vcs_type, ignore);
installer_fixture!(update_prefer_lowest_stable);
-installer_fixture!(update_reference);
-installer_fixture!(update_reference_picks_latest);
-installer_fixture!(update_removes_unused_locked_dep);
-installer_fixture!(update_requiring_decision_reverts_and_learning_positive_literals);
+installer_fixture!(update_reference, ignore);
+installer_fixture!(update_reference_picks_latest, ignore);
+installer_fixture!(update_removes_unused_locked_dep, ignore);
installer_fixture!(
- update_security_advisory_matching_direct_dependency,
- ignore = "mozart binary cannot yet run this fixture"
+ update_requiring_decision_reverts_and_learning_positive_literals,
+ ignore
);
+installer_fixture!(update_security_advisory_matching_direct_dependency, ignore);
installer_fixture!(
update_security_advisory_matching_indirect_dependency,
- ignore = "mozart binary cannot yet run this fixture"
+ ignore
);
-installer_fixture!(update_syncs_outdated);
+installer_fixture!(update_syncs_outdated, ignore);
installer_fixture!(update_to_empty_from_blank);
-installer_fixture!(update_to_empty_from_locked);
+installer_fixture!(update_to_empty_from_locked, ignore);
installer_fixture!(update_with_all_dependencies);
installer_fixture!(update_without_lock);
-installer_fixture!(updating_dev_from_lock_removes_old_deps);
-installer_fixture!(updating_dev_updates_url_and_reference);
+installer_fixture!(updating_dev_from_lock_removes_old_deps, ignore);
+installer_fixture!(updating_dev_updates_url_and_reference, ignore);