aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/shirabe/src/downloader/zip_downloader.rs
AgeCommit message (Collapse)Author
2026-08-02fix(downloader): restore late binding in getLocalChanges/update pathsnsfisis
PHP's FileDownloader::getLocalChanges and ::update call $this->download() / $this->install() / $this->remove() / $this->getInstallOperationAppendix(), which late-bind to the concrete downloader class. The Rust port embeds the parent as `inner`, so delegating these methods to FileDownloader pinned the calls to FileDownloader's own implementations: `status` built the compare tree without extracting the archive (flagging every file of dist-installed packages as changed), and `update` re-installed the raw dist file instead of extracting it. Thread the concrete downloader in as `this: &dyn DownloaderInterface` via shared helpers (base_get_local_changes / base_update) and pass `self` from each delegating downloader. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-20fix(process-executor): un-ignore 11 tests by implementing execute_async mock ↵nsfisis
support ProcessExecutor::execute_async's mock branch was an unimplemented todo!(), blocking every test whose code path calls it (feature-branch git diffing, system-unzip/7z fallback extraction). Implement it by: - Adding Process::__mock (mirroring the existing ZipArchive::__mock pattern) so execute_async can resolve with a fabricated, already- terminated Process instead of spawning a real subprocess. - Extracting the sync mock's expectation-matching logic into a shared ProcessExecutor::mock_match, wrapping the mock state in a RefCell so it works from execute_async's &self/&mut self receivers. - Setting error_output/capture_output from the mock branch, matching PHP's ProcessExecutorMock::executeAsync sharing doExecute with the sync path; execute_async now takes &mut self for this (safe, since the borrow only needs to live through the synchronous setup, not across the .await). - Turning a strict-mode expectation mismatch from a panic!() into a shirabe_php_shim::RuntimeException Err, mirroring PHPUnit's AssertionFailedError extending \RuntimeException: PHP call sites that catch (\RuntimeException $e) around a mocked git/hg/svn call (e.g. Git::get_mirror_default_branch, GitDriver::supports) treat a mismatch as an ordinary recoverable failure, and now so does the port. The RefMut is dropped before firing an expectation's optional callback so a re-entrant callback doesn't panic on double-borrow. Also fixes two real bugs found while porting test_private_repository_ no_interaction: GitHub::authorize_oauth and GitLab::authorize_oauth checked their domains config via PhpMixed::as_array(), which only matches the Array (map) variant, but github-domains/gitlab-domains default to PhpMixed::List, so the check always returned false and OAuth token lookup was silently skipped. Use the in_array shim instead, matching PHP's in_array() semantics. Also fix Git::run_command's "capture credentials from git remote -v" call, which used the panic- swallowing execute_args wrapper instead of a fallible execute(), so a mock mismatch there couldn't reach get_mirror_default_branch's catch. Un-ignores: - zip_downloader_test::test_system_unzip_only_{good,failed} - zip_downloader_test::test_non_windows_fallback_{good,failed} - event_dispatcher_test::test_dispatcher_outputs_error_on_failed_command - root_package_loader_test::test_feature_branch_pretty_version - version_guesser_test::test_guess_version_reads_and_respects_non_feature_branches_configuration_for_arbitrary_naming{,_regex} - version_guesser_test::test_remote_branches_are_selected - github_driver_test::test_private_repository_no_interaction (also adds the missing #[serial], since it seeds the shared Git::VERSION static that vcs_repository_test::test_load_versions depends on for real) - init_command_test::test_get_git_config, made deterministic by pointing HOME at a throwaway dir with its own .gitconfig instead of depending on the host's global git config Deduplicates the GitVersionGuard/RestoreEnv test-drop-guard idioms into tests/common/test_case.rs instead of reimplementing them per file. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18chore: rustfmtnsfisis
2026-07-18refactor(downloader): take &self across the downloader hierarchynsfisis
Concurrent package operations call into the same downloader instances through Rc<RefCell<dyn DownloaderInterface>>; with &mut self methods every call holds a RefMut across its awaits, which panics with 'already mutably borrowed' the moment two operations overlap. This is groundwork for fanning out InstallationManager's download/install loops (same rework HttpDownloader/CurlDownloader already got). - DownloaderInterface/ChangeReportInterface/ArchiveDownloader/ VcsDownloader methods now take &self; as_change_report_interface returns &dyn instead of &mut dyn. - Implementors move their genuinely mutable state behind cells: FileDownloader.additional_cleanup_paths, the archive downloaders' cleanup_executed, ZipDownloader.zip_archive_object, VcsDownloaderBase.has_cleaned_changes, GitDownloader's stash/discard/ cache maps and GitUtil, SvnDownloader.cache_credentials, PerforceDownloader.perforce. FileDownloader.io gains a RefCell layer so get_local_changes can keep PHP's NullIO swap under &self. - ProcessExecutor::execute_async now returns a future that captures everything up front instead of borrowing the executor, and call sites build the future before awaiting, so no borrow on the shared executor is held while a subprocess runs. - Filesystem::remove_directory_async becomes remove_directory_async_via taking the Rc handle: the Filesystem is only borrowed for the sync head/tail, never across the rm subprocess await (sync borrow_mut users like rename/ensure_directory_exists would otherwise collide). - DownloadManager async call sites hold shared borrows only. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-18perf(process-executor): make execute_async genuinely concurrentnsfisis
execute_async was a serial pump: it queued a job, then drove it to completion itself via wait_id()'s blocking usleep loop before returning, so concurrent callers never overlapped even when polled together through FuturesUnordered. Rewrite it as a single &self async fn mirroring the CurlDownloader/ HttpDownloader rework: a tokio Semaphore sized by max_jobs (COMPOSER_MAX_PARALLEL_PROCESSES, PHP parity) gates admission, the child is started non-blocking, and an async 1ms sleep loop pumps is_running()/check_timeout() while yielding to the reactor so sibling jobs genuinely run in parallel. The Job table, STATUS_* lifecycle, start_job/mark_job_done/count_active_jobs/wait/wait_id all had no remaining callers and are removed. &self also lets callers hold only a shared borrow across their awaits (zip_downloader, version_guesser, filesystem via the new get_process_handle), which would otherwise panic with 'already mutably borrowed' once two async jobs overlap on the same Rc<RefCell<ProcessExecutor>>. The async mock branch no longer consumes the expectation before hitting its todo!(): the panic made that bookkeeping unobservable. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-18perf(regex): eliminate per-call clone overhead in preg_* dispatchnsfisis
regex::Regex::clone() does not share the underlying meta engine's search-cache pool, so every fresh clone pays a ~10us warmup cost on its first use. Two changes together eliminate this across nearly all preg_* call sites: - A php_regex! macro resolves PHP-style patterns to a per-call-site &'static regex::Regex (via regex-macro's LazyLock), applied at the majority of call sites throughout the codebase. - Call sites still passing dynamic pattern strings go through PATTERN_CACHE, which now stores Arc<(Regex, bool)> and hands out Arc::clone()s instead of cloning the Regex itself. PregPattern::resolve() returns a ResolvedPattern enum (Arc or 'static reference) rather than an owned Regex, so neither path ever clones the Regex proper. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-04fix(pcre): restore missing regex delimiters in ported patternsnsfisis
Several Preg::*() call sites lost their PHP delimiter (and in one case the `i` modifier) during porting, since preg_*() expects the delimiter to be preserved in the caller's pattern literal and stripped internally. This made compile_php_pattern panic or silently misparse the pattern. Un-ignore the Version tests that were blocked by this bug.
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-27refactor: fix compiler warnings and clippy warningsnsfisis
2026-06-26test: port 35 auth/installer/io/zip/bitbucket tests; implement date_creatensfisis
Port auth_helper (14), library_installer (8), console_io (7), zip_downloader (3), git_bitbucket_driver (3) tests. Implement date_create/strtotime for the ISO8601/ RFC3339/relative formats Composer uses (unknown input -> None, no silent guess). Fix production bugs: Question::is_assoc list-vs-assoc, auth_helper gitlab-domains list handling, LibraryInstaller RefCell double-borrow, ZipArchive::extract_to ErrorException propagation. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24refactor(process): take cwd as Option<&str> instead of IntoExecCwdnsfisis
Replace the generic cwd parameter backed by the IntoExecCwd trait with a concrete Option<&str> across execute/execute_args/execute_tty/execute_async. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-20feat(symfony-process): port full Process class from PHPnsfisis
Faithfully port every method, field and constant of Symfony's Process.php into process.rs, replacing the reduced stub. Add the supporting pipes module (PipesInterface/AbstractPipes/UnixPipes/ WindowsPipes), ProcessUtils and the missing process exceptions (LogicException/InvalidArgumentException) with constructors. Methods now return anyhow::Result where PHP throws, take the env argument and a bool-returning callback, and borrow &mut for status-updating accessors; all callers are updated accordingly. Extend the php-shim with proc_open/proc_close (PHP-compatible signatures), proc_get_status, proc_terminate, posix_kill, uniqid, ftruncate, ftell_stream, fseek3, stream_get_contents3 and env helpers. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20refactor(php-shim): drop Box wrapping from PhpMixed List/Arraynsfisis
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>
2026-06-20refactor: auto-fix clippy warningsnsfisis
2026-06-14feat(php-shim): implement random_int/random_bytes with fastrandnsfisis
PHP's random_int/random_bytes are cryptographically secure, but Composer does not rely on that property, so a non-cryptographic PRNG suffices. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14refactor(pcre): drop Result from Preg method return typesnsfisis
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>
2026-06-14refactor(pcre): drop strict-groups Preg variantsnsfisis
Rust's type system already distinguishes participating from non-participating capture groups via Option, so the *StrictGroups methods add no safety here. Remove them and switch callers to the plain variants.
2026-06-08refactor(external-packages): drop component segment from symfony pathsnsfisis
Align the Symfony namespace mapping with the documented convention (symfony::component::X -> symfony::X) and remove now-unused console stub files. Update all import paths across the workspace. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-05feat(downloader): wire ArchiveDownloader extraction and Path/Zip overridesnsfisis
Implement ArchiveDownloader for Zip/Tar/Gzip/Xz/Phar/Rar so install() extracts the archive (extract + rename) instead of doing FileDownloader's plain file rename, and route install/prepare/cleanup through the mixin. ArchiveDownloader::extract becomes &mut self to match the concrete implementations. Route ZipDownloader's bespoke download() (unzip-command static init) and PathDownloader's symlink/junction/mirror download/install/remove through the DownloaderInterface trait (path: String -> &str). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-05feat(downloader): wire VcsDownloader subclasses via shared downloadersnsfisis
Share downloaders as Rc<RefCell<dyn DownloaderInterface>> in DownloadManager and make DownloaderInterface/VcsDownloader take &mut self, matching PHP's mutable-by-reference downloader objects. This lets Git/Svn/Hg/Fossil/Perforce implement VcsDownloader and route download/install/update/prepare/cleanup through the trait instead of todo!(), and wires the as_* downcast hooks end-to-end. ChangeReportInterface::get_local_changes becomes &mut self since FileDownloader downloads to a compare dir; get_commit_logs/reapply_changes gain &mut self / Result to match the concrete implementations. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-03feat(downloader): wire as_* downcasts for file/archive/path/git downloadersnsfisis
Override DownloaderInterface's as_change_report_interface / as_vcs_capable_downloader_interface / as_dvcs_downloader_interface so PHP-style instanceof checks resolve to the concrete sub-interface: FileDownloader and the six archive downloaders (Zip/Tar/Gzip/Xz/Rar/Phar) plus PathDownloader gain ChangeReportInterface (archives/path delegate to the inner FileDownloader), PathDownloader exposes VcsCapableDownloaderInterface, and GitDownloader exposes DvcsDownloaderInterface. The default None impls remain correct for downloaders that do not implement a given sub-interface, so their stale TODO markers are dropped. VCS downloaders' ChangeReport/VcsCapable conformance follows separately. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-27refactor(package): pass package handles by value throughoutnsfisis
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-26refactor(io): share IOInterface via Rc<RefCell<dyn _>> handlensfisis
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-23refactor(promise): drop \React\Promisensfisis
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-23refactor(promise): rewrite promise bodies to async/awaitnsfisis
Mechanically convert promise-returning function bodies to async/await: resolve() returns the value directly, forwarding calls get .await, and simple .then chains become await sequences. Also collapse the installer double-Option (Result<Option<Option<PhpMixed>>> -> Result<Option<PhpMixed>>). Hard spots that depend on the Loop::wait / job-machine boundary (accept/reject orchestration, closures capturing &mut self, batch waits) are left intact and marked with TODO(phase-c-promise) for manual porting. The crate does not compile yet; traits still need #[async_trait]. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-23refactor(promise): change functions returning PromiseInterface to async fnnsfisis
2026-05-22refactor: share Pool via Rc<RefCell>nsfisis
Convert Pool to Rc<RefCell<Pool>> so Solver, Decisions, and RuleSetGenerator share it, resolving the todo!() placeholders that blocked the dependency resolver (Phase C shared ownership). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20refactor: re-export module items to shorten import pathsnsfisis
2026-05-20fix(compile): fix all remaining compile errorsnsfisis
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19fix(compile): fix more random compile errorsnsfisis
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19fix(compile): fix various compile errorsnsfisis
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17fix(compile): implement abstract class traits across all typesnsfisis
Implement BaseCommand trait and other abstract class traits across all command, downloader, io, package, and VCS driver types. Also fix trait method signatures for composer_mut and io_mut to return mutable references to Option rather than Option of mutable references.
2026-05-17chore(style): cargo fmtnsfisis
2026-05-16feat(port): port ZipDownloader.phpnsfisis
2026-05-12feat(init): add scaffold filesnsfisis