aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/shirabe-semver
AgeCommit message (Collapse)Author
2026-08-20perf(semver): build CompilingMatcher's cache key without allocatingnsfisis
CompilingMatcher::match formats `<operator><constraint>;<version>` into a fresh String on every call, including the cache hits the key exists to serve. Profiling put the formatting at 2.9 % of self time, more than the match it guards. Build the key into a reused thread-local buffer and copy it only when there is a miss to record. Taking the version as `&str` rather than `String` removes the copy the callers made for the same reason: `optimize_by_identical_dependencies` allocated one per candidate package in its innermost loop. laravel/framework require --no-install (warm cache, network disabled): instructions:u 9142799608 -> 8895247586 (-2.7 %) cycles:u 4626440169 -> 4496152041 (-2.8 %) wall (hyperfine, 25 runs) 1.239 s +- 0.014 s -> 1.227 s +- 0.016 s (-1.0 %) monolog/monolog is unchanged (102.1 ms -> 101.6 ms, within noise). composer.lock is byte-identical for both packages. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-20perf(semver): memoize Intervals::isSubsetOf on its operand pairnsfisis
isSubsetOf builds a throwaway `MultiConstraint([candidate, constraint])` and hands it to `Intervals::get`, whose cache key is the constraint's string form. That MultiConstraint is fresh on every call, so its memoized string form is always cold and the whole intersection has to be stringified recursively -- profiling put `AnyConstraint: Display::fmt` at 3.6 % of self time, more than the interval computation the cache exists to skip. Cache the answer on the pair of operand strings instead. Both operands are long-lived, so each one's own string memo stays warm and the throwaway intersection is never built on a hit. laravel/framework require --no-install (warm cache, network disabled): instructions:u 9885142257 -> 9142874710 (-7.5 %) cycles:u 4858265879 -> 4444135669 (-8.5 %) wall (hyperfine, 20 runs) 1.322 s +- 0.018 s -> 1.224 s +- 0.011 s (-7.4 %) monolog/monolog is unchanged (101.6 ms -> 100.3 ms, within noise). composer.lock is byte-identical for both packages. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-19perf(semver): return the memoized interval collection by handlensfisis
Intervals::get() memoizes generateIntervals() results, but the port deep-cloned the IntervalCollection out of the cache on every hit, where PHP hands the array back by copy-on-write. On `require laravel/laravel` that is 282k calls, 99% of them hits. Store and return Arc<IntervalCollection> so a hit costs a refcount bump. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-19perf(semver): memoize MultiConstraint's string formnsfisis
composer/semver memoizes MultiConstraint::__toString() into $this->string, but the port recomputed it on every call. On `require laravel/laravel` that meant 837k stringifications visiting 1.7M child constraints, all of them feeding the CompilingMatcher and Intervals cache keys. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-18refactor(preg): add preg_is_match for existence-only call sitesnsfisis
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>
2026-08-18refactor(preg): fold preg_match into preg_match2nsfisis
preg_match copied every group into a Vec<Option<String>> while preg_match2 handed back the borrowed captures. They now differ only in the offset argument, so preg_match delegates with offset 0 and its callers read groups through PregMatches::get. Going through preg_match2 also makes preg_match honour the PCRE A modifier, which it used to ignore; no caller passes such a pattern. VersionParser::manipulate_version_string takes an index accessor instead of a slice, and VersionParser::normalize matches against a copy of the subject because the captures outlive the assignments to $version. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-17refactor(preg): return the preg_* $matches instead of filling an out-paramnsfisis
PHP fills `$matches` through a by-ref parameter, which the port mirrored with a `&mut` out-param plus a bool or count return. Every caller then had to declare an empty binding one line ahead of the call, and nothing in the type said the binding is only meaningful when the call succeeded. Return the matches instead: preg_match() and preg_match2() hand back an Option, and the three preg_match_all* functions hand back the collection they used to fill. The occurrence count the two map-shaped preg_match_all* functions used to return is the length of any one of the map's columns, so it is not lost -- Preg::match_all() and friends derive it via occurrence_count(). preg_replace2() keeps its `count: Option<&mut usize>`: that one is not derivable from the replaced string, and callers that do not want it pay nothing for passing None. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-16refactor(preg): import preg_*() instead of qualifying themnsfisis
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-16refactor: narrow pub(crate) items to privatensfisis
Porting mapped every PHP `protected` member onto `pub(crate)`, which is wider than nearly all of them need. Each item demoted here is reached only from the module that defines it, so the crate-wide visibility conveyed nothing. Every `pub(crate)` that survives has at least one reader in another module of the same crate. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-09build(cargo): fill in the package metadatansfisis
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-09docs(license): carry each ported package's license in its cratensfisis
The MIT packages Composer and Shirabe are ported from require their copyright notices to be kept, and the Composer notice was only reachable through the submodule. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-08refactor(semver): replace Constraint's OP_*/STR_OP_* with CmpOpnsfisis
PHP's version_compare takes its operator as a string, so the shim's port did too, and Constraint carried two families of operator constants plus translation tables to convert between the string form and its own int codes. Five copies of those tables had accumulated across Constraint, CompilingMatcher and the plugin value bridge. version_compare now takes a CmpOp, which makes an invalid operator unrepresentable and removes the tables' reason to exist. Constraint stores a CmpOp and keeps only the string parsing its constructor needs; getOperator, compile and CompilingMatcher::match speak CmpOp as well. PHP's OP_* numbering stays observable: a plugin reads the raw integer off the Constraint object over RPC, so get_operator_constant and its new inverse hold that 0..5 mapping. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-06feat(plugin): let links and release dates cross the RPC boundarynsfisis
The link getters and setters and the release date accessors were explicit errors for every non-empty value, because an immutable value has no entity to point a handle at. They now cross as materialized values: the descriptor names the real class and the constructor arguments, and each side builds a genuine instance of its own. The semver constraint a link holds is encoded structurally rather than re-parsed from its string form, so the pretty strings and the conjunctive flag survive the crossing. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-25refactor: replace redundant clones with movesnsfisis
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-20fix(semver): stop classical pattern matching 6+ digit versionsnsfisis
The regex crate parses PCRE's possessive \d{1,5}+ as a stacked repetition (?:\d{1,5})+, i.e. \d+, so date versions like 20121020 matched the classical pattern and normalized to 20121020.0.0.0 instead of falling through to the date(time) pattern like PHP. The plain \d{1,5} is equivalent to the possessive form here per the regex-porting rules. Un-ignore test_find_recommended_require_version which this had blocked. 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-06-28refactor: add linternsfisis
2026-06-27refactor: fix compiler warnings and clippy warningsnsfisis
2026-06-26test: port 24 command/repository/package/util tests; add TlsHelpernsfisis
Port command (9), util gitlab/forgejo/tls (6), package (6), repository (3) tests. Implement TlsHelper. Fix porting bugs: config_command extra merge, RootAliasPackage setters, ValidatingArrayLoader isset, repository_factory name generation, forgejo exception code, version_parser error chaining. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25feat(filesystem): port Symfony Filesystem methodsnsfisis
Faithfully port the Symfony Filesystem component methods (copy, mkdir, exists, touch, remove, chmod, rename, symlink, hard_link, read_link, make_path_relative, mirror, is_absolute_path, dump_file, append_to_file, temp_nam) from the PHP source, using existing php-shim functions and std where no shim exists. chown/chgrp need chown(2) (no std/shim equivalent) and the mirror filter-iterator branch is unmodeled; both left as todo!() with documented reasons. The four Composer\Util\Filesystem helpers mistakenly stubbed here stay todo!(). 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-24refactor(semver): re-export shirabe-semver at crate root, drop ↵nsfisis
composer::semver stubs Flatten shirabe-semver's modules into glob re-exports at the crate root and route all consumers through the short paths. Remove the duplicate composer::semver stubs from shirabe-external-packages in favor of the shirabe-semver types. 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-14refactor: auto-fix clippy warningsnsfisis
2026-06-14refactor: fix warningsnsfisis
2026-06-14refactor(pcre): return bool from preg_match shimnsfisis
preg_match can only return 1 or 0 now that compile failure panics, so return bool and update all call sites accordingly. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-14refactor(pcre): treat regex compile failure as fatal in shimnsfisis
The preg_* shim helpers wrapped their results in Option/Result solely to signal a regex that failed to compile. Composer never feeds a pattern that fails at runtime, so such a failure is a programming error: panic instead and drop the Option/Result wrappers, updating all callers. preg_replace_callback keeps its Result return type since the callback itself is fallible. preg_match_groups is removed in favor of preg_match at its sole call site. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-23refactor(semver): change ConstraintInterface to a closed enumnsfisis
Replace the dyn ConstraintInterface trait objects with an AnyConstraint enum closing over its four implementors (Simple, Multi, MatchAll, MatchNone), mirroring the earlier Rule enum conversion. Rename constraint.rs to simple_constraint.rs to match the renamed Constraint type. 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-20chore: allow unused codensfisis
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-17chore: cargo clippy --fixnsfisis
2026-05-17fix(semver): resolve shirabe-semver compile errorsnsfisis
- Replace RefCell with Mutex in Constraint for thread safety - Add clone_box() to ConstraintInterface for cloning trait objects - Propagate Result from Constraint::new() and unwrap at call sites - Fix VersionParser instantiation (unit struct, not fn) - Add indexmap dependency to shirabe-semver
2026-05-17chore(style): cargo fmtnsfisis
2026-05-17feat(port): port VersionParser.phpnsfisis
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-17feat(port): port Intervals.phpnsfisis
Add Clone derives to Constraint, Interval, and DevConstraintSet (needed for IntervalCollection). Add preg_match/preg_replace/preg_split stubs to shirabe-php-shim. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16feat(port): port Constraint.phpnsfisis
2026-05-16feat(port): port MultiConstraint.phpnsfisis
2026-05-16feat(port): add as_any/is_disjunctive to ConstraintInterface (needed for ↵nsfisis
MultiConstraint)
2026-05-16feat(port): port Semver.phpnsfisis
2026-05-16feat(port): port Bound.phpnsfisis
2026-05-16feat(port): port Comparator.phpnsfisis
2026-05-16feat(port): port Interval.phpnsfisis
2026-05-16feat(port): port CompilingMatcher.phpnsfisis
2026-05-16feat(port): port MatchAllConstraint.phpnsfisis
2026-05-16feat(port): port MatchNoneConstraint.phpnsfisis
2026-05-16feat(port): port ConstraintInterface.phpnsfisis
2026-05-16feat(port): add template files for composer/semvernsfisis