aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/shirabe-php-shim/src/var.rs21
-rw-r--r--crates/shirabe/src/dependency_resolver/problem.rs15
-rw-r--r--crates/shirabe/tests/installer_test.rs6
3 files changed, 34 insertions, 8 deletions
diff --git a/crates/shirabe-php-shim/src/var.rs b/crates/shirabe-php-shim/src/var.rs
index 513c3e88..dd0592f8 100644
--- a/crates/shirabe-php-shim/src/var.rs
+++ b/crates/shirabe-php-shim/src/var.rs
@@ -185,6 +185,27 @@ pub fn is_numeric_to_int(value: &PhpMixed) -> i64 {
}
}
+/// Approximates PHP's `<=>` for two strings: if both are numeric strings, compare numerically
+/// (as PHP does), otherwise fall back to a byte-wise comparison.
+///
+/// TODO: this only covers the string/string case of PHP's loose comparison. PHP's `<=>` has many
+/// more special-cased rules across other operand type combinations (bool, array, null, object,
+/// numeric-string-vs-non-numeric-string, ...). Extend this if a new caller needs those.
+pub fn loosely_compare(a: &str, b: &str) -> std::cmp::Ordering {
+ if is_numeric_string(a) && is_numeric_string(b) {
+ match (a.trim().parse::<i64>(), b.trim().parse::<i64>()) {
+ (Ok(na), Ok(nb)) => na.cmp(&nb),
+ _ => {
+ let na: f64 = a.trim().parse().unwrap_or(0.0);
+ let nb: f64 = b.trim().parse().unwrap_or(0.0);
+ na.partial_cmp(&nb).unwrap_or(std::cmp::Ordering::Equal)
+ }
+ }
+ } else {
+ a.cmp(b)
+ }
+}
+
pub fn instance_of<T>(_value: &PhpMixed) -> bool {
// TODO(phase-d): PHP `instanceof` needs the runtime class of the value, which PhpMixed::Object
// does not carry.
diff --git a/crates/shirabe/src/dependency_resolver/problem.rs b/crates/shirabe/src/dependency_resolver/problem.rs
index 5ff949a9..a2072372 100644
--- a/crates/shirabe/src/dependency_resolver/problem.rs
+++ b/crates/shirabe/src/dependency_resolver/problem.rs
@@ -13,9 +13,9 @@ use indexmap::IndexMap;
use shirabe_external_packages::composer::pcre::{CaptureKey, Preg};
use shirabe_external_packages::symfony::console::formatter::OutputFormatter;
use shirabe_php_shim::{
- LogicException, PhpMixed, defined, extension_loaded, implode, in_array, php_regex, phpversion,
- spl_object_hash, sprintf, str_replace, str_starts_with, stripos, strpos, strtolower, substr,
- substr_count, version_compare,
+ LogicException, PhpMixed, defined, extension_loaded, implode, in_array, loosely_compare,
+ php_regex, phpversion, spl_object_hash, sprintf, str_replace, str_starts_with, stripos, strpos,
+ strtolower, substr, substr_count, version_compare,
};
use shirabe_semver::constraint::AnyConstraint;
use shirabe_semver::constraint::MultiConstraint;
@@ -119,8 +119,13 @@ impl Problem {
return rule2_prio.cmp(&rule1_prio);
}
- self.get_sortable_string(pool, &rule1.borrow())
- .cmp(&self.get_sortable_string(pool, &rule2.borrow()))
+ // PHP: getSortableString(...) <=> getSortableString(...). RULE_LEARNED keys are
+ // '-'-joined literal ids (e.g. "-95"), which PHP's <=> compares numerically when both
+ // sides are numeric strings rather than byte-by-byte.
+ loosely_compare(
+ &self.get_sortable_string(pool, &rule1.borrow()),
+ &self.get_sortable_string(pool, &rule2.borrow()),
+ )
});
Self::format_deduplicated_rules(
diff --git a/crates/shirabe/tests/installer_test.rs b/crates/shirabe/tests/installer_test.rs
index 4c9b3d3a..c12d9cfd 100644
--- a/crates/shirabe/tests/installer_test.rs
+++ b/crates/shirabe/tests/installer_test.rs
@@ -1362,7 +1362,7 @@ macro_rules! raw_pool_test {
}
slow_test! {
- slow_github_issues_7665 => "github-issues-7665.test", ignore = "TODO(phase-d): known-failing fixture under COMPOSER_POOL_OPTIMIZER=0";
+ slow_github_issues_7665 => "github-issues-7665.test", ignore = "TODO(phase-d): unknown reason. Needs further investigation.";
}
pool_optimizer_test! {
@@ -1590,7 +1590,7 @@ raw_pool_test! {
raw_pool_github_issues_4319 => "github-issues-4319.test";
raw_pool_github_issues_4795_2 => "github-issues-4795-2.test";
raw_pool_github_issues_4795 => "github-issues-4795.test";
- raw_pool_github_issues_7051 => "github-issues-7051.test", ignore = "TODO(phase-d): known-failing fixture under COMPOSER_POOL_OPTIMIZER=0";
+ raw_pool_github_issues_7051 => "github-issues-7051.test";
raw_pool_github_issues_8902 => "github-issues-8902.test";
raw_pool_github_issues_8903 => "github-issues-8903.test";
raw_pool_github_issues_9012 => "github-issues-9012.test";
@@ -1645,7 +1645,7 @@ raw_pool_test! {
raw_pool_provider_can_coexist_with_other_version_of_provided => "provider-can-coexist-with-other-version-of-provided.test";
raw_pool_provider_conflicts => "provider-conflicts.test";
raw_pool_provider_conflicts2 => "provider-conflicts2.test";
- raw_pool_provider_conflicts3 => "provider-conflicts3.test", ignore = "TODO(phase-d): known-failing fixture under COMPOSER_POOL_OPTIMIZER=0";
+ raw_pool_provider_conflicts3 => "provider-conflicts3.test";
raw_pool_provider_dev_require_can_satisfy_require => "provider-dev-require-can-satisfy-require.test";
raw_pool_provider_gets_picked_together_with_other_version_of_provided_conflict => "provider-gets-picked-together-with-other-version-of-provided-conflict.test";
raw_pool_provider_gets_picked_together_with_other_version_of_provided_indirect => "provider-gets-picked-together-with-other-version-of-provided-indirect.test";