aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates
AgeCommit message (Collapse)Author
2026-06-29feat(require): update locker hash with stability flags rewriternsfisis
Resolve the remaining todo! in update_requirements_after_resolution by passing the stability-flags rewriter closure to Locker::update_hash, porting the static closure from RequireCommand.php. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29feat(audit): implement get_packages non-locked branchnsfisis
Port AuditCommand::getPackages's non-locked path: build an InstalledRepository from the local repository and return its packages, filtered by RootPackage requires when --no-dev is set. The prior TODO(phase-c) assumption (InstalledRepository::new vs get_local_repository type mismatch) no longer holds since both sides use RepositoryInterfaceHandle. Enables the two previously ignored audit command tests. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29feat(package): implement RootAliasPackage root getters via owned returnsnsfisis
It is faithful to PHP's by-value array/string semantics. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29fix(json): use php_truthy for JsonManipulator content validity guardsnsfisis
The `!@json_decode($children)` guards in addSubNode/removeSubNode were translated as `is_null() || as_bool() == Some(false)`, which drops PHP's other falsy cases (empty array/string, "0", 0). At the removeSubNode site (assoc=true) this diverged from Composer: an empty object node decodes to an empty array, which PHP treats as falsy and aborts on, but the Rust guard kept going. Replace both with php_truthy, the faithful rendering of PHP `!`, preserving the deliberate empty-`{}` behavior difference between the assoc=false (addSubNode) and assoc=true (removeSubNode) sites. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-29feat(console): implement output instanceof downcasts in process/progress helpersnsfisis
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29fix(advisory): pass IO as shared handle to Auditor::auditnsfisis
Auditor::audit took io as &mut dyn IOInterface, forcing the audit and installer post-audit call sites to hold a borrow_mut() on the shared IO RefCell for the whole call. During advisory fetching the repositories write to their own clones of the same handle, so the borrow_mut() collided with their borrow() and panicked with 'RefCell already mutably borrowed' on 'audit --locked'. Take the Rc<RefCell<dyn IOInterface>> handle instead so writes borrow briefly and never overlap. Un-ignore the locked-audit regression test that this unblocks. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29refactor(json): replace seld/jsonlint with serde_jsonnsfisis
Validate JSON syntax with serde_json's parse errors in JsonFile, and detect duplicate keys in ConfigValidator with a hand-written serde visitor, dropping the now-unused JsonParser/Lexer/DuplicateKeyException ports. ParsingException is kept as the thrown error type and downcast signal. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29chore(lint): ban bare `use anyhow::Result` and fully qualify itnsfisis
Add a no_banned_use linter that forbids importing anyhow::Result, and update all call sites to reference it via its fully-qualified path so it is never confused with std::result::Result. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28test(show): clarify ignore reason for empty platform sectionnsfisis
The platform: section is empty because PlatformRepository::get_packages routes to ArrayRepository::initialize instead of its own initialize, which needs the still-todo!() runtime::constant() shim. Record the real blocker. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28fix(repository): flatten InstalledRepository and unwrap filter repos in shownsfisis
flattenRepositories must recurse into InstalledRepository (which extends CompositeRepository in PHP) and ShowCommand must unwrap FilterRepository when categorizing repos. Without this, installed/locked/platform packages all fell through to the "available" bucket, dropping the version column and per-section grouping. Un-ignores 10 show_command tests. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28fix(installer): execute install/update/uninstall ops in execute_batchnsfisis
execute_batch only awaited prepare(), leaving the install/update/ uninstall + cleanup + repo.write promise chain as a todo!() stub, so packages were downloaded to cache but never installed into the target directory. Wire the operation step (mirroring PHP's promise chain), propagate errors from the install/update/uninstall wrappers instead of swallowing them with .ok()?, and write the repo after each op. Un-ignore the create-project functional tests and the install/remove command tests this unblocks. The remaining --no-install case still fails on a separate install-path bug; its ignore reason is updated to match.
2026-06-28test(installer): port InstallerTest unit and integration harnessnsfisis
Port composer/tests/Composer/Test/InstallerTest.php. testInstaller (the provideInstaller cases) is fully ported and passes; the three integration tests port doTestIntegration in full (the .test fixture loader, FactoryMock, the in-process console Application with install/update commands, and the PHPUnit assertStringMatchesFormat matcher) and remain #[ignore]'d since the install pipeline is not yet executable end-to-end. Add test-only `__`-seams to the concrete types the test depends on, since their consumers (e.g. Locker takes the concrete InstallationManager) and the subclass-style mocks have no trait to mock: InstallationManager (recording mock + as_any), Factory (__create_mock), VersionGuesser, and InstalledFilesystemRepository. The production path (mock: false) is unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28test(functional): port AllFunctionalTest integration harnessnsfisis
Implements the todo!() stubs in all_functional_test.rs by faithfully porting parseTestFile, cleanOutput and the inline %regex% EXPECT matcher, plus a subprocess runner that drives CARGO_BIN_EXE_shirabe (in place of PHP's composer.phar) over the reused Fixtures/functional .test files. The five fixtures are wired as individual #[serial] #[ignore] tests with per-fixture reasons: the two create-project cases need network + a real git clone, and the three update cases need the not-yet-implemented Plugin API. test_build_phar stays an ignored stub since Rust has no phar build. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28feat(process): implement PhpExecutableFinder::find env fallbacksnsfisis
Replace the todo!() with the PHP_PATH and PHP_PEAR_PHP_BIN env-var fallbacks and the trailing PATH-based php lookup. The \PHP_BINARY/ \PHP_SAPI branch and the \PHP_BINDIR seed dir are skipped since the shim does not model the running PHP interpreter, but the final lookup still resolves php via PATH with empty extra dirs. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28fix(http): avoid nested tokio runtime panic in download pathnsfisis
The CurlDownloader owned a tokio runtime and block_on'd reqwest from its sync tick(), while the repository/installer/downloader sync bridges each created another Runtime and block_on'd async fns that reach that leaf. Driving one Runtime::block_on from within another panics with "Cannot start a runtime from within a runtime", hit by `require` when fetching p2 metadata. Switch CurlDownloader to a blocking reqwest client (its own internal thread, never nested) and replace the per-call Runtime::new().block_on bridges with a no-reactor sync_executor::block_on helper. No awaited future parks on a reactor once the only async I/O is blocking, so the helper can be nested freely. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28fix(util): restore PHP delimiters in ported regex patternsnsfisis
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28refactor: add linternsfisis
2026-06-28feat(package): impl alias getter delegation via owned String returnsnsfisis
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28feat(repository): impl RepositoryInterface for Artifact/Path/Vcs reposnsfisis
The structural methods are inherited from ArrayRepository in PHP, where the lazy package load is driven by the overridden initialize(). Without virtual dispatch, each repository now ensures that load via a &self ensure_initialized() before delegating to the inner ArrayRepository. This required moving the repositories' lazily-populated state behind interior mutability (RefCell/Cell) and adding &self find_package_internal /find_packages_internal helpers on ArrayRepository. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28test(json): drop JsonFormatterTest stubnsfisis
JsonFormatter is intentionally unported in crates/shirabe/src/json, so the ignored todo!() stub test serves no purpose. Remove the file and its module declaration. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28chore: add comment to PhpMixednsfisis
2026-06-28test(downloader): cfg-gate XzDownloaderTest skip on Windows/32bitnsfisis
Replace the todo!() markTestSkipped placeholders in set_up with a compile-time cfg gate on the test function, mirroring PHP's setUp skips on Windows and 32bit. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28test(command): port HomeCommandTest useCaseProvider casesnsfisis
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28test(command): port DiagnoseCommandTest casesnsfisis
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28test(tests): use mockall for hand-written interface mocksnsfisis
Replace hand-written mock/stub structs that re-implemented PHPUnit mock-builder behavior (record-and-verify, manual call counters, unreachable!() guards) with mockall::mock! locals across: - package/loader: MockLoader, VersionGuesserMock - command: ArchiveManager/RepositoryManager/EventDispatcher mocks - util: ConfigSource/AuthJson mocks (auth_helper, bitbucket, github, forgejo, gitlab) - repository/vcs: github_driver NullConfigSource - installer: CountingInstaller, RecordingBinaryInstaller, and the DownloadManager mock (formerly common/downloader_stub.rs, now deleted) - downloader: download_manager create_downloader_mock Verification (counts/args) now lives in mockall expectations checked on drop. installation_manager BinaryInstaller is left hand-written because its as_binary_presence_interface seam returns Some(&mut self), which mockall cannot express; io_stub and io_mock are left as-is. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28test(util/git): port interactive Bitbucket OAuth runCommand testnsfisis
Implement the four privateBitbucketWithOauthProvider cases that were stubbed as an ignored todo!(). Extend IOStub with per-question askAndHideAnswer responses and auth pre-seeding so the stateful OAuth flow can be driven without willReturnCallback, and inject a mock HttpDownloader plus no-op config sources to mirror PHPUnit's Config mock. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28test(repository): port testRepositoryWritesInstalledPhpnsfisis
Implement the previously-ignored test, which dumps installed.php via FilesystemRepository::write and byte-matches the Composer fixture. The package link setters needed by configureLinks are now reachable through the __set_provides/__set_replaces test hatches, so the PHP getPackage + configureLinks shape can be reproduced faithfully. Also switch both InstallationManager stubs in this file to a single mockall mock, replacing the hand-rolled impls and call counter. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28fix(php-shim): emit NUL bytes as concatenation in var_exportnsfisis
PHP var_export breaks NUL bytes out of single-quoted string literals as `' . "\0" . '` because a raw NUL byte is invalid in PHP source. The shim embedded the raw byte instead, diverging from Composer's generated installed.php (where references can contain NUL). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28test(console): correct inaccurate test skip reasonsnsfisis
setCatchErrors is an old-Symfony compatibility shim that exists in neither Composer's PHP class nor Shirabe, and setAutoExit(false) is the default in Shirabe, so neither is a reason a test is unportable. Drop those mentions and point the application_test ignores at the real blocker: do_run's script-command registration is still a todo!(). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28test(console): port DocumentationTest::testCommandnsfisis
Add __base_application accessor on ApplicationHandle so the test can build an ApplicationDescription the way console commands do. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-28test(package/archiver): port testGitExcludesnsfisis
Process::fromShellCommandline and ZipArchive are now ported, so the git pipeline + zip reading have faithful equivalents. Kept #[ignore]d: the finder applies .gitattributes rules through BaseExcludeFilter::generate_pattern, whose (?=$|/) look-ahead regexes the regex crate cannot compile (same blocker as test_manual_excludes); also needs a git executable. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28test(package/version): port testFindRecommendedRequireVersionnsfisis
Ported faithfully via PackageHandle::new + __set_extra (now available on PackageHandle). Kept #[ignore]d: date-based cases expose a shirabe_semver normalize divergence (v20121020 -> 20121020.0.0.0), not a test-port issue. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28test(downloader): port Fossil/Hg testRemovensfisis
The FilesystemMock seam (already used by FileDownloaderTest) intercepts removeDirectoryAsync before any rm -rf, so the prior execute_async blocker no longer applies. getDownloaderMock gains the optional filesystem param. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28test(factory): port testDefaultValuesAreAsExpectednsfisis
The IOMock and ConfigStubBuilder helpers now cover the writeError verification and the get('disable-tls')=>true stub the PHP test needs. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28test(config): port testProhibitedUrlsWarningVerifyPeernsfisis
The IOMock helper is now available, so the verify_peer/verify_peer_name SSL warning case can be exercised instead of left as todo!(). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28test(command/status): port testLocallyModifiedPackagesnsfisis
Replace the todo!() stub with a faithful port of StatusCommandTest's data-provided locally-modified-packages cases (source/dist), kept #[ignore]d since install does not yet populate vendor/ offline. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-28test(util): port MetadataMinifier expand testnsfisis
minify is intentionally unported, so only the expand half of testMinifyExpand() is exercised. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-27feat(installer): register default installers after Composer Rc is builtnsfisis
LibraryInstaller and PluginInstaller upgrade the Composer back-reference in their constructors, so they could not be built inside Rc::new_cyclic where the weak handle is not yet upgradeable. Defer create_default_ installers until after the cyclic Rc is established, where the weak handle resolves, and implement it to register Library -> Plugin -> Metapackage with a single shared BinaryInstaller. To share one BinaryInstaller (as Composer does), LibraryInstaller's binary_installer becomes Rc<RefCell<dyn BinaryInstallerInterface>> instead of an owned Box; PluginInstaller and the __set_binary_installer test seam follow. This clears "Unknown installer type: metapackage". Un-ignores the six remove tests that now pass; the remaining install/remove tests are re-labeled for the next blocker (InstallationManager::execute_batch still leaves the install/cleanup/repo.write promise chain as a todo!() stub, so package operations do not actually execute). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-27feat(command/update): port UpdateCommand input definitionnsfisis
Replace the empty set_definition stub with the full InputArgument/ InputOption set from Composer's UpdateCommand. The symfony input modeling was already complete; this was the last command still passing an empty definition, which made it reject its own options. Un-ignores test_no_security_blocking_allows_insecure_packages (now passing) and re-labels the six remaining update tests with their actual blockers (regex porting, resolver temporary-constraint, interactive mode, bump-after-update solver pool) since the old "empty InputDefinition" reason no longer applies. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-27refactor(http): present reqwest instead of faking curl_versionnsfisis
- StreamContextFactory: User-Agent reports the HTTP stack as "reqwest" - RequestProxy::supports_secure_proxy: always true (reqwest+rustls can always TLS to a proxy); drop the now-dead curl<7.52 guard in get_curl_options - DiagnoseCommand::get_curl_version: phase-D TODO placeholder Empirically verified: reqwest sends no default User-Agent (shirabe sets it explicitly) and accepts https:// proxy URLs. init+install output stays byte-identical to Composer. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-27fix(json): encode empty stdClass fields as {} not []nsfisis
Empty PhpMixed::Array now serializes as [], so the several places that build a PHP `new \stdClass` via an empty Array were emitting [] where Composer writes {}. Use PhpMixed::Object for those empty-object cases: - InitCommand: require / require-dev - Locker::fixupJsonDataType: stability-flags / platform / platform-dev - JsonConfigSource fallback: require/config keys that must stay objects Align the affected test expectations with Composer: JsonFile::read() decodes with assoc=true, collapsing the on-disk {} back to [], so reads expect []. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-27fix(autoload): correct generated autoloader blank linesnsfisis
PHP heredocs drop the newline before the closing marker, so a two-blank-line fragment must port to "\n\n", not "\n\n\n", and the static initializer needs a "\n" after the $initializer placeholder. This makes autoload_real.php and autoload_static.php byte-identical to Composer's output. Rewrite the templates as raw strings mirroring the PHP heredocs. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-27fix(php-shim): encode empty PhpMixed::Array as []nsfisis
PHP arrays do not distinguish an empty map from an empty list, and json_encode([]) always emits []. The Serialize impl emitted {} for an empty associative array, which diverged from Composer when computing the lock file content-hash for a composer.json with an empty require. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-27test: serialize env-var-dependent testsnsfisis
Several tests read process-global env vars and set/clear them via TearDown but were not #[serial], so parallel execution could race. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-27test: port Composer tests unblocked by mockall, add seamsnsfisis
Port 11 categories of previously-ignored Composer tests now reachable with the mockall crate: DownloadManager, VCS/Perforce/File downloaders, VersionSelector, PlatformRepository, Auditor, installer/FilesystemRepository, RootPackageLoader, util auth/http, commands, and Cache. Extract test seams additively on concrete structs as *Interface traits (Runtime, HhvmDetector, VersionGuesser, RepositorySet, Perforce, BinaryInstaller) plus mock-field seams (Cache, Filesystem); consumers take trait objects. Mocks are defined locally in the test crates via mockall::mock!, since automock-generated mocks are cfg(test)-gated and invisible across the integration-test boundary. dataProviders are ported in full; tests blocked by unported shims stay #[ignore] with documented reasons rather than reduced or weakened. Fix product bugs surfaced by the ports: - util/github: use the exception code, not the HTTP status, for 401/403 - advisory: serialize empty audit maps as [] to match PHP json_encode - repository/filesystem and downloader/file: fix RefCell double-borrow panics Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-27test: add mockall cratensfisis
2026-06-27fix(command/show): match PHP null/isset semantics in package outputnsfisis
Three porting mismatches caused show/info output to diverge from PHP: - "not found" hint appended " in /composer.json" whenever the working-dir key existed; PHP uses isset(), which is false for the null default. Now only appended when the value is non-null. - printPackages and generatePackageTree inserted "" for a missing description instead of null, so isset() rendered a spurious trailing space (and JSON emitted "" instead of null). Both now preserve null. Un-ignores the eight rendering-gap tests these fix (plus one already passing), and rewrites the remaining ignore reasons to name the real blocker (package categorization, --no-dev filtering, RefCell borrow, installer resolution) instead of a stale generic message. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-27fix(json): include property name in required-property errorsnsfisis
The jsonschema crate reports a missing required property against its parent object, leaving the instance path empty at the root. This skipped the "PROPERTY : MESSAGE" formatting that Composer produces. Append the missing property name to the path so the output shape matches. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-27refactor(composer): hold managers behind *Interface traitsnsfisis
Composer/PartialComposer exposed its RepositoryManager, InstallationManager, EventDispatcher, Locker, DownloadManager, AutoloadGenerator and ArchiveManager as concrete types, but Composer's public setters (setDownloadManager() etc.) let plugins swap in subclasses. Introduce a *Interface trait per manager and store each as Rc<RefCell<dyn ...Interface>> so a replacement is honored. Only Composer's slots and the sinks fed from its accessors become trait objects; managers injected concretely at construction keep their concrete references, matching PHP semantics. Fluent setters on the affected classes now return () and Locker::update_hash is de-generified to a boxed FnOnce so the traits stay object-safe. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-27refactor(main): minor refactoringnsfisis