aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/mozart/src/commands/install.rs
AgeCommit message (Collapse)Author
2026-05-02refactor(commands): split install/update into CLI execute + library runnsfisis
Carve commands::install::execute and commands::update::execute into thin CLI-arg-driven wrappers + run() entry points that take (working_dir, args, console, repositories, executor) directly. The wrappers build a production RepositorySet (Packagist) + FilesystemExecutor from cli, then dispatch to run; in-process tests will call run directly with an empty RepositorySet (Composer's `'packagist' => false` test config) and a tracing InstallerExecutor. The install -> update fallback (no composer.lock present) now goes through update::run, forwarding the caller's repositories + executor so test mocks survive the edge. Also drop the now-dead InstallConfig::no_cache field — install_from_lock stopped consuming the cache when FilesystemExecutor was extracted in the earlier DI plumbing pass, so the field has no effect. All 136 enabled installer fixtures + 114 mozart-registry tests + 541 mozart lib tests still green; clippy clean. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02refactor(registry): plumb RepositorySet and executor through callersnsfisis
ResolveRequest and LockFileGenerationRequest now take Arc<RepositorySet> instead of a raw Cache. install_from_lock now accepts &mut dyn InstallerExecutor instead of constructing FilesystemExecutor internally. Both changes expose the DI injection points needed by the upcoming in-process test harness, where Packagist must be replaced with an empty RepositorySet (Composer's `'packagist' => false` test config) and filesystem install execution must be replaced with a tracing recorder (Composer's InstallationManagerMock). The eager VCS scan and inline-package preload still happen inside resolve(), so the RawRepository array is kept on ResolveRequest as raw_repositories - migrating those through RepositorySet remains a follow-up. RepositorySet gains with_packagist and empty constructors so production callers and future tests have a uniform construction shape. All 136 enabled installer fixtures + 114 mozart-registry tests + 541 mozart lib tests still green; clippy clean. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02refactor(registry): introduce Repository and InstallerExecutor traitsnsfisis
Sets up DI scaffolding for in-process installer E2E tests, mirroring how Composer's PHPUnit suite swaps Packagist (FactoryMock) and the install manager (InstallationManagerMock) without touching the network or filesystem. Additions: - Repository trait + RepositorySet (Composer's RepositoryInterface analog), with PackagistRepository, InlinePackageRepository, VcsRepository impls. - InstallerExecutor trait (Composer's InstallationManager analog) with FilesystemExecutor extracted from install_from_lock. install_from_lock now delegates per-package install/uninstall verbs to FilesystemExecutor; console output orchestration stays in the caller so existing --EXPECT-OUTPUT-shape assertions remain comparable. No behavior change - all 136 enabled installer fixtures still pass. Also tightens the installer_fixture\! ignore form to a single token (installer_fixture\!(name, ignore)) for readability. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01feat(registry): support inline 'type: package' repositoriesnsfisis
Composer's PackageRepository lets composer.json embed full package metadata under repositories[].package, mirroring the on-disk Packagist response shape. The vast majority of installer fixtures under composer/tests/Composer/Test/Fixtures/installer (179 of 189) rely on this — they declare every package they need inline rather than hitting the network. Three pieces wire this into Mozart: 1. mozart-core::package::RawRepository: relax `url` to Option<String> (Composer enforces presence per repo type, not at JSON parse) and add `package: Option<Value>` to receive the inline definition, which can be a single object or an array. 2. mozart-registry::inline_package: a new module that walks `&[RawRepository]`, picks out type=package entries, and reshapes each `package` payload into a PackagistVersion (auto-computing version_normalized when omitted, matching Packagist's output). 3. resolver::resolve and lockfile::generate_lock_file: feed inline packages into the SAT pool builder and short-circuit the Packagist fetch when generating the lock entry for a resolved inline package. The package-name set is shared with the existing VCS-skip logic so the seed and transitive loops don't double-fetch. One additional install-time change: in install_from_lock, packages that have neither dist nor source are now skipped silently instead of bailing with "no dist or source information". This mirrors Composer's MetapackageInstaller (no installer for type=metapackage) and is also what Composer's own AllFunctionalTest exercises via InstallationManagerMock — most inline-package fixtures define synthetic packages with no download metadata, expecting the install operation to be recorded but not actually run. Net effect: installer fixture scoreboard jumps from 7/187 to 103/187. The 84 fixtures still ignored hit issues unrelated to inline-package plumbing — aliases, replace/provide chains, dev-reference handling, allow-list updates, etc. — and are tracked separately. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01fix(install): preserve LockedPackage extra_fields in installed.jsonnsfisis
Composer's InstalledFilesystemRepository::write() dumps the full package via ArrayDumper, so flags like `abandoned` and `default-branch` (which Mozart parks in LockedPackage::extra_fields) should round-trip from composer.lock into vendor/composer/installed.json. locked_to_installed_entry was zeroing the destination's extra_fields, silently stripping these flags every time installed.json got rewritten. Carry the extra_fields map across verbatim. The install-forces-reinstall-if-abandon-changes installer fixture is already exit-0 green at the harness layer; this aligns the actual end-state with Composer's EXPECT-INSTALLED so a future EXPECT-INSTALLED comparison won't re-flag this gap. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01feat(core): reject root composer.json that requires its own namensfisis
Mirrors Composer\Package\Loader\RootPackageLoader::load(): if the root package's "name" appears as a key in its own "require" or "require-dev" map, fail loudly before reaching the resolver. Without this, Mozart would silently let the request hit Packagist (which has no entry for the root's vendor/name) and report a misleading "could not be found" error. Wired into install::execute (when a lock file is present) and update::execute (the no-lock fallback path). Carries the same wording as Composer's RuntimeException so a future EXPECT-OUTPUT comparison will match. Also extends the installer test harness: when a fixture sets EXPECT-EXCEPTION but no EXPECT-EXIT-CODE, assert that Mozart exits non-zero. Full exception-class matching remains a follow-up (see .ken/test_design.md §7.2). Closes the gap exercised by the install-self-from-root installer fixture. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01feat(install): verify platform requirements before install_from_locknsfisis
Mirrors Composer's platform-requirements check during Installer::doInstall(): merge platform requires from the lock's platform/platform-dev fields with the root composer.json require/require-dev (composer.json wins on duplicate keys), then verify them against the detected runtime platform. If any are missing or unsatisfied, print the standard "Your lock file does not contain a compatible set of packages" message followed by Problem 1..N entries and exit with DEPENDENCY_RESOLUTION_FAILED (2) instead of silently proceeding to "Nothing to install" with exit 0. Closes the gap exercised by the outdated-lock-file-with-new-platform-reqs-fails installer fixture. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01feat(install): verify lock file satisfies composer.json requiresnsfisis
Mirrors Composer's Installer::doInstall() check: before installing from an existing composer.lock, walk every root require (and require-dev in dev mode) and confirm the lock contains a satisfying package. If any are missing or fail the constraint, print the standard bullet-list diagnostic and exit with LOCK_FILE_INVALID (4) instead of blindly attempting to install and failing later with a misleading "no dist or source information" error. Closes the gap exercised by the outdated-lock-file-fails-install installer fixture. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01refactor: fix clippy warningsnsfisis
Replace if-let/else-return with `?`, swap `as_ref().map(|k| k.as_slice())` for `as_deref()`, and switch test fixtures from `vec\![]` to array literals where ownership is unneeded. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-02-24fix(cache): enable dist archive caching for all commandsnsfisis
files_cache was Option<&Cache> and install_from_lock always passed None, so downloaded zip/tar archives were never cached. Make the parameter non-optional (&Cache) and wire it through every command that downloads dist archives (install, update, require, remove, create-project, archive). The Cache internally respects --no-cache via its enabled flag, so the Option wrapper was unnecessary. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23refactor(cli): route command output through Console abstractionnsfisis
Replace direct println\!/eprintln\! calls with console.write(), console.info(), and console.write_stdout() across all command handlers to respect verbosity settings. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23fix(cli): align install/update output with Composer conventionsnsfisis
- Migrate eprintln\! to Console for consistent colored output - Use Composer terminology in lock file operations: Locking instead of Installing, Upgrading/Downgrading instead of Updating - Add is_downgrade() helper to distinguish upgrades from downgrades - Pass Console through install_from_lock for proper output handling Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23feat(vcs): add mozart-vcs crate for VCS repository supportnsfisis
Implement VCS driver/downloader infrastructure mirroring Composer's VCS subsystem. Includes drivers for GitHub, GitLab, Bitbucket, Forgejo, Git, Hg, and SVN with API-based metadata resolution, plus source downloaders for Git/Hg/SVN. Integrates into mozart-registry via vcs_bridge module to scan VCS repositories and feed discovered packages into the SAT resolver. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23fix(install): add CLI option validation, download-only wiring, and ↵nsfisis
apcu-prefix implicit enable - Restrict --prefer-install to source/dist/auto and --audit-format to table/plain/json/summary via clap value_parser - Error when --prefer-install is combined with --prefer-source/--prefer-dist - Wire --download-only through InstallConfig to skip autoloader and installed.json - Implicitly enable --apcu-autoloader when --apcu-autoloader-prefix is set - Apply same validation fixes to update, require, remove, create-project commands Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23fix(dump-autoload): add config defaults, CLI validation, and class count outputnsfisis
Read optimize-autoloader, classmap-authoritative, apcu-autoloader from composer.json config section. Reject --dev with --no-dev and --strict-psr/ --strict-ambiguous without --optimize. Emit pre/post generation messages with class count in optimized mode. Track ambiguous class mappings and exit with code 2 when --strict-ambiguous detects conflicts. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22refactor(console): add console_format! proc macro and migrate all commandsnsfisis
Introduce a Symfony Console-style tag macro that replaces verbose patterns like `console::info(&format!("text {name}"))` with `console_format!("<info>text {name}</info>")`. Supports all 6 tag types (info, comment, error, question, highlight, warning) with format argument distribution across multiple tagged segments. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22fix(install): fall back to update when composer.lock is missingnsfisis
Match Composer behavior: instead of failing with an error when no composer.lock is present, show a warning and delegate to the update command to resolve dependencies from composer.json. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22refactor(async): migrate from blocking HTTP to async/await with tokionsfisis
Replace reqwest::blocking with async reqwest across the entire codebase. All command execute functions, registry API calls (packagist, downloader, resolver, lockfile), and the main entry point now use async/await with the tokio runtime. The pubgrub resolver runs on spawn_blocking since its DependencyProvider trait is synchronous, using Handle::block_on for async I/O within that context. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22refactor(workspace): split monolithic crate into 6 workspace cratesnsfisis
Extract modules from the single `mozart` crate into 5 focused library crates to improve compilation parallelism and architectural clarity: - mozart-constraint: version constraint parser (independent) - mozart-core: base types, console, validation, platform utilities - mozart-archiver: archive creation (tar, zip, bzip2) - mozart-registry: Packagist API, cache, resolver, downloader, lockfile - mozart-autoload: autoloader generation and PHP scanner Refactor Console::from_cli and build_cache_config to accept primitive args instead of &Cli to break circular dependencies. Introduce [workspace.dependencies] for centralized version management. Remove 9 unused direct dependencies from the CLI crate. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21feat(console): add structured error handling, verbosity, and suggestionsnsfisis
Implement Phase 7.2 error handling & UX infrastructure: - Add exit_code module with MozartError, bail()/bail_silent() helpers, and Composer-compatible exit code constants (0-5, 100) - Redesign Console struct with Verbosity enum (Quiet/Normal/Verbose/ VeryVerbose/Debug), ANSI auto-detection via IsTerminal, and verbosity-gated output methods (info/verbose/debug/error) - Thread Console through all 33 command execute() signatures - Replace all std::process::exit() calls with structured MozartError returns handled in main() - Migrate eprintln\! status messages to console.info() for quiet-mode suppression - Add suggest module with Levenshtein distance and "Did you mean?" formatting for future package name suggestions Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21feat(cache): add filesystem-backed cache with TTL expiration and size-limited GCnsfisis
Implement a cache module with CacheConfig and Cache structs supporting read/write (string and binary), atomic writes via temp+rename, TTL-based expiration, and size-limited garbage collection. Wire the repo cache into packagist.rs and resolver.rs for API response caching, and the files cache into downloader.rs for dist archive caching. Implement the clear-cache command with full clear and --gc modes. All existing call sites pass None for backward compatibility. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21feat(autoload): add classmap scanning, optimize, APCu, platform checks, and ↵nsfisis
strict-psr Add PHP file scanner (php_scanner.rs) with class/interface/trait/enum detection, comment/string/heredoc stripping, and PSR-4/PSR-0 validation. Extend autoload generation with: classmap directory scanning, --optimize mode (PSR-4/PSR-0 to classmap), --classmap-authoritative, --apcu caching with optional prefix, platform_check.php generation, and --strict-psr violation reporting. Wire new options through dump-autoload, install, require, update, and remove commands. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21feat(install): add InstallConfig, platform warnings, and download progressnsfisis
Replace positional boolean parameters in install_from_lock with a structured InstallConfig. Add platform requirement warnings, download progress display, classmap-authoritative autoloader support, and prefer-source detection across install/update/require/remove commands. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21feat(depends): implement depends and prohibits commands with shared ↵nsfisis
dependency logic Add the `depends` (why) and `prohibits` (why-not) commands that query the dependency graph to answer "which packages require X?" and "which packages prevent version Y of X from being installed?" respectively. Introduces the shared `dependency` module with package loading from lock file or installed.json, forward/inverted dependency graph walking, recursive traversal with cycle detection, and table/tree output formatters. Adds `conflict` field to LockedPackage for conflict-based prohibition detection, updating all struct literals across install, remove, require, and update test helpers. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21feat(update): implement update command with resolver-based dependency updatesnsfisis
Add full update command supporting --lock (content-hash refresh only), --dry-run, --no-install, --no-dev, --prefer-stable, --prefer-lowest, and partial updates (named packages). Extract install_from_lock() from install.rs for shared use. Add Stability::parse() to package.rs. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21feat(autoload): generate Composer-compatible PHP autoloader filesnsfisis
Implement autoloader generation that produces all standard Composer autoloader files (autoload.php, autoload_real.php, autoload_static.php, autoload_psr4.php, autoload_namespaces.php, autoload_classmap.php, autoload_files.php, installed.php) plus embeds ClassLoader.php, InstalledVersions.php, and LICENSE from the Composer submodule. Wire into the install command (gated by --no-autoloader) and replace the todo!() in dump-autoload with a working implementation. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21feat(install): implement install command with lock-based package installationnsfisis
Replaces the todo!() stub with a full implementation that reads composer.lock, computes install/update/skip/remove operations by comparing against vendor/composer/installed.json, downloads packages via the downloader module, and writes the updated installed registry. Handles edge cases: missing lock file, stale lock file, no dist info, empty packages, --dry-run, --no-dev, deprecated flags, and vendor directory cleanup after removals. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11change commands::*::execute() signaturesnsfisis
2026-02-11enable workspacensfisis