| Age | Commit message (Collapse) | Author |
|
Auditor.php calls ConsoleIO::sanitize() with a single argument, so
$allowNewlines is the default true. The port passed false, stripping
newlines out of advisory titles, links and ignore reasons before they
reach the table renderer.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
|
Messages that instruct the user to run a command named the Composer
binary. Shirabe ships as its own binary, so the hints now name it.
File names (composer.json, composer.lock), the "composer" repository
type and prose about Composer itself are untouched. The installer and
functional integration fixtures live in the Composer submodule and
cannot be edited, so their expected output is normalized on load.
|
|
The capture groups were discarded at 162 of the preg_match call sites,
which only tested the Option. They now call preg_is_match, which lets the
regex engine skip capture tracking.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
|
Every call site but one passed offset 0. The remaining one, the UTF-8
chunking loop in Application, slices the subject instead: its pattern has
no anchor or lookaround, so matching a suffix is equivalent to starting
the search at that offset.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
|
Preg had shed everything it owned: after the last few rounds its methods
were one-line forwards to the shim's preg_*(), differing only in a
default argument or a wrapper the caller unwrapped anyway. The 460 call
sites now name the shim function, and shirabe-pcre is gone from the
workspace along with its LICENSE entry.
The forwards expand as they read: isMatch becomes
preg_match2(.., 0).is_some() (is_none() where PHP negates it), isMatch3
and match3 drop the .is_some(), matchAll counts through
preg_match_all2(..).occurrence_count(), and replace4/replace5 spell out
the limit and count arguments preg_replace2 takes. Callbacks are the one
place the shapes differ: preg_replace_callback carries an error out of
the callback, so the fourteen infallible closures wrap their result in
Ok() and expect() it back.
Config::process() is the fifteenth, and it drops the `error` cell it
captured to smuggle a failure past a closure that could only return a
String. The `?` in the closure now carries it, which is what the PHP
does -- a throw from the callback leaves preg_replace_callback at the
failing match rather than running the remaining replacements and
reporting the last error.
The module doc that explained why composer/pcre's exceptions and
*StrictGroups() variants have no counterpart moves to the shim's preg
module, where the functions it describes live.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
|
doWrite, doOverwrite and sanitize accept PHP's string|list<string>, which
this port modelled as PhpMixed. Every call site inside ConsoleIO passes a
single string, so take &str and return String instead, dropping the
(array) casts and the to_string_list helper.
Auditor is the only caller that passed a list: it builds table rows, whose
cells must stay separate, so it now sanitizes each cell. select() likewise
sanitizes each choice while projecting them into the keyed form.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
|
str_contains(), str_starts_with() and str_ends_with() were thin wrappers
over the str methods of the same semantics. Call sites now use
contains()/starts_with()/ends_with() directly.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
|
shirabe-symfony-console crate
Move `Symfony\Component\Console` out of shirabe-external-packages and
into its own crate, so the path is
`shirabe_symfony_console::application::Application` instead of
`shirabe_external_packages::symfony::console::application::Application`.
The `delegate_to_inner!` and `delegate_command_trait_impls_to_inner!`
macros move with it.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
|
Move `Composer\Pcre` out of shirabe-external-packages and into its own
crate, so the path is `shirabe_pcre::preg::Preg` instead of
`shirabe_external_packages::composer::pcre::preg::Preg`.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
|
Ported exceptions were flat structs reached with `downcast_ref`, so
Composer's `catch (\RuntimeException $e)` only matched the exact leaf
type and `get_class($e)` had nothing to report. Each exception now
embeds an instance of the class it extends and travels inside an
`AnyThrowable`; `Catch::catch`/`catch_mut` walk that chain, and
`PhpClass::php_class_name` yields the PHP FQCN.
Dropping the `std::error::Error` impls from the exception types leaves
`AnyThrowable` as the only route into an `anyhow::Error`, so the walk
cannot be bypassed. A `no_exception_downcast` linter catches the
`downcast::<X>()` calls that would now silently answer `None`.
Three sites change behavior as a result: the `TransportException`
exit-code override reaches `MaxFileSizeExceededException`, the
`catch (\LogicException)` in findSimilar() reaches its subclasses, and
rendered exception titles carry the real class name rather than a
guess. `get_class_err()` is no longer a `todo!()`, which re-enables
FilesystemRepositoryTest::testCorruptedRepositoryFile.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
|
The ported docblocks copied @param and @return straight from the PHP
source. When such a tag carries nothing but a type and an argument name,
the Rust signature already states it, so the line is noise. Tags whose
text adds prose beyond the type are kept.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
|
PHP's JsonFile::encode throws a RuntimeException when json_encode fails; the
port swallowed that into an .unwrap() marked TODO(phase-c). Return
anyhow::Result from encode/encode_with_options and propagate at every call
site (print_table and list_repositories become Result-returning to carry it).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
|
The two summary templates are compile-time constants, so the runtime
sprintf shim is unnecessary; carry the tag and the "ignored " prefix
through the passes list instead of pre-built template strings.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
|
PHP's SecurityAdvisoryPoolFilter stores advisory *object references* in
$securityRemovedVersions, and PoolOptimizer::applyRemovalsToPool hands
that array to the new Pool by copy-on-write. Porting AnySecurityAdvisory
as a value type turned both of those into deep copies.
Measured on `require laravel/framework` (offline, warm cache): 113
distinct advisories were duplicated into 314,309 copies of ~1.08 KiB,
retaining 331.9 MiB in the filter loop and another 331.9 MiB when
apply_removals_to_pool cloned the whole map.
3.54s -> 2.62s (-26%), peak RSS 975 MB -> 343 MB, which matches the upper
bound measured by ablation. Composer runs the same workload in 1.49s.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
|
PHP's BufferIO extends ConsoleIO, so $io instanceof ConsoleIO matches
it; the port models that inheritance as composition, making the plain
ConsoleIO downcast reject BufferIO and throw where PHP renders tables.
Also try a BufferIO downcast and unwrap its inner ConsoleIO, which
unblocks the two FORMAT_TABLE cases and un-ignores test_audit.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
|
|
|
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>
|
|
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>
|
|
|
|
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>
|
|
|
|
execute nested the already-built InstalledRepository inside a second
InstalledRepository, tripping the assertion that an InstalledRepository may not
contain another. PHP adds a PlatformRepository to the existing composite via
addRepository; do the same.
Un-ignores CheckPlatformReqsCommandTest::test_failed_platform_requirement.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
|
The Table helper modeled a row's cells as PhpMixed and recovered the concrete
TableCell/TableSeparator types via runtime instance_of, leaving the entire
mixed/array bridge (to_row_vec, cell_colspan, row_get, ...) as todo!(). Replace
that with proper Row/Cell enums:
Row = HeaderDivider | Separator(TableSeparator) | Cells(Vec<Cell>)
Cell = Null | Value(String) | Cell(TableCell) | Separator(TableSeparator)
The internal header/body boundary that PHP detects by object identity
($divider === $row) becomes the dedicated Row::HeaderDivider variant. Style
arguments (PHP string|TableStyle) become a StyleName enum, so Table::new no
longer panics in resolve_style's instance_of stub; TableStyle derives Clone so
named styles resolve from the registry.
PhpMixed-based callers (SymfonyStyle::table, render_table, auditor's sanitize)
bridge via From<PhpMixed> for Cell/Row at the boundary.
Un-ignores LicensesCommandTest text-format cases (4) and
BaseDependencyCommandTest::why; output matches PHP exactly. Removes ~15 impl
todo!()s in the Table helper.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
|
|
|
The List and Array variants of PhpMixed boxed their elements
unnecessarily. Store PhpMixed values directly and update all callers
accordingly.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
|
|
|
The Preg methods panic on PCRE failure (per the file header rationale),
so their anyhow::Result wrappers never carried an Err.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
|
Convert every sprintf() call with a compile-time literal format string to
format!, implementing Display for PhpMixed (delegating to php_to_string) so
PhpMixed values render with PHP string semantics through {}. Also merge the
format!-wrapped and conditional-literal dynamic sites into single format!
calls. Genuinely runtime format strings (table styles, configurable error
messages, command synopsis, progress-bar modifiers, regex-built messages)
still go through sprintf.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
|
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
|
Introduce shim functions and constants, replacing the ad-hoc chrono
format strings and parse helpers used as phase-b placeholders.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
|
Implement the foundational PhpMixed conversion infrastructure
(From<bool|i64|f64|String>, order-sensitive PartialEq matching PHP ===)
and resolve the category-G phase-b TODOs that depend on it:
- Fix VCS driver cache paths that discarded parsed JSON or diverged on
null caches (svn/forgejo/gitlab/git-bitbucket/github).
- Wire up real conversions previously stubbed or dropped: suggests
platform config, audit ignore-severities, composer_repository search
and ProviderInfo, class_loader prefix/classmap merges, locker lock
diff comparison, advisory JSON serialization, SPDX license fields.
- Make GenericRule take a typed ReasonData; populate RULE_ROOT_REQUIRE
with the constraint and convert PhpMixed at the call sites.
|
|
Resolve category F phase-b TODOs (class-string, instanceof, get_class,
method_exists, __FILE__, Reflection API, downcast).
- VcsRepository: dispatch drivers through a VcsDriverKind enum
(instantiate/supports/php_class_name) and add constructors to the
concrete VCS drivers
- repository downcasts via RepositoryInterfaceHandle::downcast_rc and
as_any (init/show commands, vcs ValidatingArrayLoader)
- BaseCommand::is_self_update_command override replaces an instanceof
- Factory::create narrows PartialComposer to ComposerHandle via as_full
- InstalledVersions gains set_self_dir/set_installed_is_local_dir,
replacing Reflection-based static property mutation
- ClassLoader::as_array_iter ports the PHP (array) cast
- drop the unnecessary __FILE__ phar branch in self-update
application get_class(command) reclassified TODO(plugin); buffer_io
StreamableInputInterface downcast and the ValidatingArrayLoader trait
redesign left as tracked TODOs.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
|
Resolve the resolvable subset of category A (shared ownership / non-cloneable
PHP class) TODOs by leaning on values that are already shared behind Rc/handle
wrappers, where cloning preserves PHP reference semantics:
- solver: call IgnoreListPlatformRequirementFilter::filter_constraint with a
cloned AnyConstraint (a Clone enum) and propagate the Result
- update_command: filter PlatformRepository out of the repository manager's
handles into a CompositeRepository (array_filter equivalent)
- package_discovery_trait: pass the real platform_requirement_filter (Rc clone)
instead of substituting ignore_nothing()
- installation_manager: pass the original full operation list (Vec<Rc<_>>
clone) as all_operations
- file_downloader: swap self.io to NullIO and restore via std::mem::replace
- auditor: reuse the PackageInterfaceHandle list across the advisory and
abandoned-package queries
- process_executor: drop the unused, lossy Clone impl
- config / array_repository: demote settled RefCell-design markers to comments
Remaining category A items (factory installer wiring, purge_packages handle
bridge, installer cache identity, reinstall flow, plugin command discovery)
stay as TODOs since correct resolution needs structural refactors.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
|
Add an Ignored variant to the advisory enum (renamed to AnySecurityAdvisory)
so the PHP three-class hierarchy PartialSecurityAdvisory -> SecurityAdvisory
-> IgnoredSecurityAdvisory maps one-to-one onto enum variants.
Replace the hard-coded auditor downcasts with as_security_advisory()
(PHP `instanceof SecurityAdvisory`, true for both full and ignored) and
as_ignored(), implementing severity/cve/source ignore filtering, the
toIgnoredAdvisory conversion, and the table/plain row output faithfully.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
|
Replace the i64 bitmask + encode_with_indent split with a JsonEncodeOptions
struct (Default = JSON_UNESCAPED_SLASHES|JSON_PRETTY_PRINT|JSON_UNESCAPED_UNICODE,
default indent). encode/write each get a default form plus an explicit
encode_with_options/write_with_options variant, mirroring PHP's optional
$options argument. write_with_options always encodes with self.indent, matching
PHP write().
Also reconcile call sites with the PHP sources: most ported sites passed 0 where
Composer omits the argument (= default flags), so JsonManipulator/ShowCommand and
JsonConfigSource now use the default options; only ComposerRepository and Locker
genuinely pass 0.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
|
Introduce the cross-cutting downcast base for PHP `instanceof` checks on
io/output trait objects: `IOInterface::as_any` (ConsoleIO/NullIO/BufferIO)
and `OutputInterface::as_console_output_interface` (promoting ConsoleOutput
to a proper ConsoleOutputInterface). Wire the resolved downcasts in
ConsoleIO error output, Auditor table format, and the event dispatcher.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
|
Implement the security advisory pool filter end to end, plus the
remaining actionable wirings it unblocked.
- Unify the PartialSecurityAdvisory|SecurityAdvisory union as the
PartialOrFullSecurityAdvisory enum and make the advisory types Clone,
so advisories can be collected and stored; Pool.security_removed_versions
now carries the union. This also unblocks PoolOptimizer's clone of the
security-removed versions.
- Thread the filter result through run_security_advisory_filter/build_pool
as anyhow::Result.
- Introduce typed PlatformRepositoryHandle and pass platform repos as
handles through determine_requirements instead of &PlatformRepository.
- Wire RuleSetGenerator's is_unacceptable_fixed_or_locked_package check
and UpdateCommand's non-locked installed-packages branch.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
|
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
|
PHP packages have reference semantics, so introduce shared-ownership
handles over an AnyPackage enum (PackageInterfaceHandle and friends)
and replace Box<dyn PackageInterface> throughout.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
|
|
|
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
|
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
|
|
|
|
|
|
|
|
|