aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/shirabe-php-shim/src
AgeCommit message (Collapse)Author
2026-06-26test: port 70 perforce/repository/downloader/installer/dispatcher testsnsfisis
Port perforce (36), locker (10), composer_repository (7), installation_manager (6), file_downloader (5), and event_dispatcher (6) tests via the mock infra. Fix production porting bugs surfaced en route: BufferIO::get_output look-behind regex, ComposerRepository list-form package iteration and initialize dispatch, gethostname and spl_autoload_functions shims; add EventDispatcher get_listeners test seam. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-26test: port 44 vcs/downloader/version tests using mock infransfisis
Port git, version_guesser, gitlab_driver, github_driver, and git_downloader tests using the ProcessExecutor/HttpDownloader mocks and IO/Config stubs. Fix production regex-porting bugs surfaced by the now-reachable paths: Url::sanitize and Response::find_header_value had non-delimited PCRE patterns; implement array_search_mixed non-strict branch and a datetime format mapping. Add HttpDownloader::__new_mock so mocked downloaders skip curl construction. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25feat(external-packages,shim): implement impl todos across componentsnsfisis
Port seld/jsonlint JsonParser (+hand-written Lexer), unblocking 10 json_file parse-error tests verified byte-for-byte against PHP. Implement Symfony Finder SplFileInfo, executable finders, String classes (byte/code-point/unicode), ZipArchive shim (via the zip crate), SPDX license validation, and shim date/stream functions. Genuinely-blocked sites (reflection, PHP runtime constants, non-UTF-8 transcoding, recursive PCRE) stay todo!() with reasons. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25feat(semver): hand-port constraint AND-split to drop look-around regexnsfisis
The PCRE delimiter `(?<!^|as|[=>< ,]) *(?<!-)[, ](?!-) *(?!,|as|$)` used to split AND-constraints relies on look-around, which the regex crate cannot compile (parse_constraints panicked). Reproduce its semantics in a hand-written `split_and_constraints` scanner shared by VersionParser and RootPackageLoader. Also model `method_exists` for the class-name form (shirabe runs no dumped Composer ClassLoader) and un-ignore the InstalledVersions tests, serialized via `#[serial]` since they share global static state. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25fix(preg): treat escaped \$ in replacement as a literal dollar signnsfisis
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25feat(json): validate JSON schema via the jsonschema cratensfisis
Replace the todo!() json_schema::Validator stub with the jsonschema crate. Errors are surfaced as 'property : message'; the message wording follows the jsonschema crate and is *not* justinrainbow-compatible. Port the ComposerSchemaTest and JsonFileTest schema cases to the new wording (noted per test). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25feat(php-shim): model $_ENV/$_SERVER as OsString snapshotsnsfisis
Rework the environment shim around getenv/putenv on the real environment and $_ENV/$_SERVER as startup snapshots, all over OsString. Migrate every caller off the old server()/server_argv() helpers and force the snapshots in main() before any putenv() runs. Document the porting rules in docs/dev/env-vars-porting.md. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24feat(php-shim): implement non-strict in_array with PHP loose comparisonnsfisis
Replace the deferred todo!() path with loose_eq, implementing PHP's == semantics for in_array's non-strict mode (numeric-string-aware comparison, bool/null coercion, recursive array comparison).
2026-06-24feat(php-shim): support JSON_PRETTY_PRINT in json_encode_exnsfisis
PHP's JSON_PRETTY_PRINT uses a 4-space indent, so use serde_json's PrettyFormatter with a 4-space indent when the flag is set.
2026-06-24refactor(php-shim): remove is_resource/is_resource_valuensfisis
2026-06-24feat(process): redesign proc_* on PhpResource process handlesnsfisis
proc_open/proc_close/proc_get_status/proc_terminate represented the process handle as a PhpMixed, which cannot hold a live child process or its pipes, so they were stubs or todo!(). Model the handle as a new PhpResource::Process variant and child pipes as a StreamBacking::Pipe, with a native Descriptor enum for descriptorspec; proc_open now returns io::Result and fills pipes as IndexMap<i64, PhpResource>. Rewire the Symfony Process pipes and the Console terminal/cursor onto the new types, removing the "PhpMixed cannot carry a PhpResource" todo!()s. The remaining todo!()s are genuine syscall leaves (proc_terminate signal delivery, stream_select, stream_set_blocking, posix_kill, pty, fd>=3) left unimplemented since no syscall crate is introduced. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24test: port more unimplemented testsnsfisis
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22feat(php-shim): implement fopen-family stream API on PhpResourcensfisis
Redesign PhpResource into a real stream handle (File/Memory backing with tracked position, eof, closed state) and unify the whole fopen family (fopen/fwrite/fread/fgets/fgetc/feof/fclose/ftell/fseek/rewind/fstat/ ftruncate/fflush and stream_get_contents/stream_copy_to_stream) on &PhpResource, replacing the split PhpMixed/PhpResource APIs and their todo!() stubs. fopen now returns Result; read functions stay String for now (TODO(phase-e) to move to byte strings). Propagate the signatures through callers: Process stdout/stderr, Cursor input, curl header/body handles (extracted into typed maps keyed by job id), Filesystem copy/safe_copy/files_are_equal, BufferIO, error_handler, platform, perforce, zip. The proc_open pipe paths cannot carry a PhpResource in a PhpMixed list, so they are left as todo!() with notes.
2026-06-22feat(json): resolve bundled Composer schema files via build.rsnsfisis
JsonFile's schema paths previously relied on php_dir() (__DIR__), which has no runtime equivalent. Add a build.rs that copies composer-schema.json and composer-lock-schema.json next to the built executable, and resolve them with std::env::current_exe(). FilesystemRepository now embeds InstalledVersions.php directly via include_str! instead of reading it through php_dir(). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-22feat(php-shim): add DOMDocument/DOMNode XML shimnsfisis
Implements a minimal, PHP-compatible subset of \DOMDocument, \DOMNode and \DOMNodeList for use by Symfony's XmlDescriptor. save_xml mirrors libxml2's formatOutput serialization (XML declaration, 2-space indent, self-closing empty elements, and no pretty-printing of text-bearing elements) and writes to a std::io::Write sink. Verified byte-for-byte against real PHP libxml. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21feat(php-shim): implement fs helpers and recursive directory iteratorsnsfisis
Give RecursiveDirectoryIterator/RecursiveIteratorIterator real backing data: the iterator walks the tree in SELF_FIRST/CHILD_FIRST order, yields SplFileInfo-like entries (is_dir/is_file/is_link/get_pathname/get_size), and a Cell cursor lets get_sub_pathname() report the current entry. Implement the std-backed file helpers: lstat, mkdir (umask-aware via DirBuilder), symlink, chmod, fileperms, fileowner, is_executable, unlink_silent, touch (create-if-absent), file()/file_put_contents3/ file_get_contents5, tempnam, umask (via /proc/self/status), and a glob() supporting *, ?, [...] and {..} brace expansion. The PhpMixed-keyed fopen stream family, disk_free_space, touch with an explicit time, opendir and DirectoryIterator remain TODO(phase-d): they need a PhpMixed stream representation or syscalls std does not expose. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21feat(php-shim): implement version_compare/spl_object_hash/clone et alnsfisis
Port php_version_compare (canonicalization + special-form ordering) and expose it via version_compare()/version_compare_2(). Implement clone() (via Clone), spl_object_hash()/spl_object_hash_process() (address-based), get_loaded_extensions() and the main-version case of phpversion(). Interpreter/reflection/autoload/eval/$GLOBALS/memory-accounting and Windows-only SAPI helpers remain TODO(phase-d): they have no equivalent in the compiled shim. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21feat(php-shim): implement sprintf/pack/unpack/base64/strip_tags and morensfisis
Implement the bulk of string.rs shims: - sprintf() with flags/width/precision/positional args for the common conversions (s/d/u/b/o/x/X/c/f/F) - pack()/unpack() for the C/c/n/v/N/V (+ s/S/i/I unpack) format codes - base64_encode()/base64_decode() (non-strict) - substr_replace, str_bitand, chr, hexdec, stripcslashes, addcslashes, number_format (round-half-away-from-zero), uniqid, strip_tags, html_entity_decode, iconv (UTF-8/ASCII identity) %e/%E/%g/%G, wordwrap, sscanf, php_strip_whitespace and non-UTF-8 iconv remain TODO(phase-d) (exact float-exponent/tokenizer/encoding-table behavior not yet ported). Divergences in ported functions are noted with TODO(phase-d) comments. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21feat(php-shim): implement exec/shell_exec/system/escapeshell*/posix_isattynsfisis
Run exec()/shell_exec()/system() through /bin/sh -c with PHP-faithful line handling and return values. Port escapeshellcmd() (Unix branch, including paired-quote handling) and escapeshellarg(). Implement posix_isatty() via std::io::IsTerminal. uid/signal/process-title helpers and proc_open-dependent status calls remain TODO(phase-d): they need a libc/syscall crate or the deferred process/signal subsystems. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21feat(php-shim): implement serialize/var_export/to_array/get_debug_typensfisis
Implement var.rs shims: serialize() (scalars/arrays with canonical integer-key normalization), var_export()/var_export_str() (PHP-faithful indentation and quoting), to_array() ((array) cast semantics), get_debug_type() and is_iterable() for the scalar/array cases. Reflection-dependent helpers (is_a, is_callable, get_class, instance_of, etc.) and object variants remain TODO(phase-d) as they need runtime class information PhpMixed does not carry. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21refactor(php-shim): drop reset()/reset_first()/end_arr() array helpersnsfisis
These slice/map wrappers mirrored PHP's internal array pointer and have no clean Rust equivalent. Remove them and replace the lone caller with direct first-element access; the rest were unused imports. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21refactor(php-shim): drop current()/key()/end() array helpersnsfisis
PHP's internal array pointer (current/key/end) has no clean Rust equivalent. Remove these todo!() shim stubs and replace each call site with direct first/last element access matching Composer's original behavior. Unblocks Config::merge of anonymous {name: false} disable entries, re-enabling test_add_packagist_repository. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21feat(php-shim): implement array sort/merge/unique/splice helpersnsfisis
Implement array_unique, array_splice, array_merge_recursive, krsort, ksort, asort, sort_with_flags and sort_natural_flag_case, plus the strnatcmp/strnatcasecmp port they rely on. Drop array_key_last and array_splice_mixed in favour of existing helpers at the call sites. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21feat(php-shim): implement gethostbyname() and inet_pton()nsfisis
2026-06-21feat(php-shim): implement microtimensfisis
Drop the get_as_float parameter; the Rust shim always returns f64. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21feat(php-shim): implement hash, hash_raw, hash_filensfisis
Support md5, sha1, sha256, and xxh3 algorithms. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21feat(php-shim): implement http_build_query via serde_urlencodednsfisis
2026-06-21refactor(php-shim): remove ArrayObject, inline IndexMap into PhpMixed::Objectnsfisis
ArrayObject was only a thin wrapper around IndexMap<String, PhpMixed> used as an empty-{} vs empty-[] marker and as the assoc=false JSON object representation; no reference semantics were involved. Inline its payload directly into PhpMixed::Object and drop the type along with the now-dead StdClass. Side effects of the unification: - ArrayObject::new was todo!(); the config --global / object-typed get paths that built PhpMixed::Object(ArrayObject::new(None)) no longer panic. - base_config_command wrote 'config' as PhpMixed::Array(empty), emitting [] instead of {}; now matches PHP's new \ArrayObject ({}). - The dead is::<StdClass>()/is::<ArrayObject>() instanceof checks in JsonManipulator are replaced with the faithful as_object() mapping. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21refactor(php-shim): remove unused methodnsfisis
2026-06-21feat(php-shim): implement filter_var email/ip/int validatorsnsfisis
Replace the todo!() bodies of filter_var_email, filter_var_ip, and filter_var_int_with_range with working validators. Like filter_var_url these are pragmatic rather than byte-for-byte compatible with PHP's hand-written filters; the divergences are noted in comments. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21refactor(php-shim): split filter_var into per-filter functionsnsfisis
Replace the dispatch-on-constant filter_var() and filter_var_with_options() with dedicated filter_var_boolean/url/email/ip and filter_var_int_with_range, dropping the FILTER_VALIDATE_* constants and updating all call sites. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21refactor(autoload): drop dead APCu cache from ClassLoadernsfisis
apcu_fetch/apcu_add only ran when apcuPrefix was non-null, but Composer never calls setApcuPrefix on the loaders it instantiates itself; the prefix is only emitted into the generated target-project autoload_real.php. So the cache branches were unreachable in Shirabe's execution paths. Remove the apcu shim and the now-dead lookups. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21refactor(math): use method-style max/min/clamp over std::cmpnsfisis
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21feat(php-shim): implement round() shimnsfisis
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21refactor(json): eliminate json_last_error in favor of Resultnsfisis
json_encode/json_encode_ex now return anyhow::Result<String> instead of Option, so callers no longer need json_last_error() to get the failure reason. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21refactor(php-shim): split lib.rsnsfisis
2026-06-21feat(php-shim): implement pure-function todo!() stubsnsfisis
Fill in the shim functions that have an easy, accurate pure-Rust port: array (merge/flip/fill_keys/slice/search/is_list), string (substr_count, strpbrk, raw/urlencode, ucfirst/ucwords, strstr, strcspn, explode limit, str_replace arrays), mb_* (strlen/substr/str_split), sort callbacks (uasort/uasort_map/uksort), levenshtein, intdiv, ceil, ctype_digit, json_encode, count_mixed and the PhpMixed/to_* boolean casts. Runtime- or crate-dependent and hard-to-port-accurately stubs (sprintf, version_compare, natural sort, hashing, etc.) are left as todo!().
2026-06-21test(tests): port setUp/tearDown as set_up/tear_down with TearDownnsfisis
Port PHP setUp/tearDown across the ported integration tests using same-named set_up()/tear_down() functions and a TearDown struct whose Drop runs tear_down(). Fixture-init setUp returns its fixtures; tmpdir-style setUp/tearDown carry state in TearDown fields. Parts that depend on unported infrastructure (PHPUnit mocks, Config::merge, the PHP error handler) stay todo!() and are only wired into ignored stubs to avoid breaking live tests. Also fix shirabe-php-shim putenv to handle the no-'=' form (PHP unsets the variable), which Platform::clear_env relies on for the env-clearing tearDowns. Co-Authored-By: Claude Opus 4.8 <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-20feat(php-shim): implement parse_url and filter_var URL/boolean filtersnsfisis
Back parse_url/parse_url_all with reqwest::Url and add the FILTER_VALIDATE_URL and FILTER_VALIDATE_BOOLEAN arms to filter_var, so Config::prohibit_url_by_config no longer hits todo!(). reqwest::Url is not a byte-for-byte port of PHP's parser; the divergences are noted with TODO(phase-c). Switch the scheme in_array in prohibit_url_by_config to strict: the needle is a string-or-null and the haystack holds only non-numeric string literals, so loose and strict comparison are provably equivalent here, avoiding a dependency on PHP loose `==` semantics. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-20fix(path): propagate PathBufnsfisis
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-20feat(php-shim): implement is_writable via filesystem metadatansfisis
Replace the todo!() with a std-only check on the path's permission bits. A TODO notes this approximates PHP's access(2)/W_OK and can diverge for files the current user does not own; to be refined with a syscall crate. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-20feat(console): implement doRenderThrowable exception renderingnsfisis
Port Symfony's Application::doRenderThrowable so command failures render the error box instead of hitting todo!(). This unblocks six CLI no-panic tests (config, depends, global, prohibits, remove, repository), whose ignore attributes are now removed. Also fill in the php-shim functions on the render path that were still todo!(): php_exception_get_code, intval, str_pad, str_split, mb_detect_encoding, mb_convert_encoding, mb_strwidth, mb_convert_variables. PHP file/line and the verbose getTrace() block have no faithful Rust equivalent; file/line use PHP's own 'n/a' fallback and the trace block is intentionally omitted. Co-Authored-By: Claude Opus 4.8 (1M context) <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(clippy): resolve idiomatic lint warningsnsfisis
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-20refactor(console): propagate getComposer's exit(1) as ExitExceptionnsfisis
Composer's Application::getComposer() calls exit(1) when a required Composer instance fails to build under areExceptionsCaught(). Replace the deep std::process::exit with a php-shim ExitException that mirrors PHP's `exit` construct: it bypasses parent::doRun()'s catch and Symfony's renderThrowable (excluded at both broad catches), so the already-written plain error message is not re-rendered and the process exits with code 1. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-20feat(php-shim): implement array_replace_recursivensfisis
Was a todo!() that panicked while building HTTP downloader options (browse, and the stream/remote filesystem option merging). Recurses only when both the existing and replacing value are arrays, merging assoc arrays by key and lists by index; otherwise the replacing value wins. Verified against PHP on a nested http/ssl option structure. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-20feat(php-shim): implement single-component pathinfonsfisis
Was a todo!() that panicked in Factory::get_lock_file (require, and the file/gzip downloaders). Handles the four PATHINFO_* single-component options by reusing dirname/basename, computing extension and filename around the last dot of the basename. Verified against PHP for eight representative paths, including dotfiles and trailing-dot names. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-20feat(php-shim): implement is_numericnsfisis
Was a todo!() that panicked when ProcessExecutor::reset_max_jobs probed COMPOSER_MAX_PARALLEL_PROCESSES (archive, diagnose, init, ...). Ints and floats are numeric; strings delegate to the existing is_numeric_string, which agrees with PHP across the tested vectors. Booleans, null and arrays are not numeric. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-20feat(php-shim): implement two-argument json_decodensfisis
Was a todo!() that panicked for every command reading composer.json (validate, status, show, update, ...). Parses via serde_json (built with preserve_order, so insertion order is kept) and converts to PhpMixed. Mirrors PHP's flagless json_decode: returns null rather than erroring on malformed input, and decodes objects to ArrayObject when assoc is false, to an associative array when true. Out-of-i64 and fractional numbers become floats, matching PHP's default non-bigint behaviour. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>