mirror of
https://github.com/elicpeter/nyx.git
synced 2026-06-27 20:29:39 +02:00
[pitboss] sweep after phase 05: 2 deferred items resolved
This commit is contained in:
parent
345b44d3cc
commit
62bd480db3
2 changed files with 140 additions and 3 deletions
|
|
@ -352,7 +352,7 @@ fn try_package_json_engines(root: &Path) -> Option<ToolchainResolution> {
|
|||
let mut in_engines = false;
|
||||
for line in content.lines() {
|
||||
let trimmed = line.trim();
|
||||
if trimmed.contains("\"engines\"") {
|
||||
if json_line_has_key(trimmed, "engines") {
|
||||
in_engines = true;
|
||||
}
|
||||
if in_engines && trimmed.contains("\"node\"") {
|
||||
|
|
@ -410,6 +410,23 @@ fn map_node_version(version: &str, origin: PinOrigin) -> ToolchainResolution {
|
|||
}
|
||||
}
|
||||
|
||||
/// Return true if `line` contains `"key":` as a JSON object key assignment.
|
||||
///
|
||||
/// Prevents false-positives from values like `"type": "require"` that would
|
||||
/// otherwise match a plain `contains("\"key\"")` check.
|
||||
fn json_line_has_key(line: &str, key: &str) -> bool {
|
||||
let needle = format!("\"{key}\"");
|
||||
let mut search = line;
|
||||
while let Some(pos) = search.find(needle.as_str()) {
|
||||
let rest = &search[pos + needle.len()..];
|
||||
if rest.trim_start().starts_with(':') {
|
||||
return true;
|
||||
}
|
||||
search = &search[pos + 1..];
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
/// Extract a version string from a JSON value like `">=18"` or `"20.x"`.
|
||||
fn extract_version_from_json_value(line: &str) -> Option<String> {
|
||||
// Find the second quoted value after the colon.
|
||||
|
|
@ -624,7 +641,7 @@ fn try_composer_json(root: &Path) -> Option<ToolchainResolution> {
|
|||
let mut in_require = false;
|
||||
for line in content.lines() {
|
||||
let trimmed = line.trim();
|
||||
if trimmed.contains("\"require\"") {
|
||||
if json_line_has_key(trimmed, "require") {
|
||||
in_require = true;
|
||||
}
|
||||
if in_require && trimmed.contains("\"php\"") {
|
||||
|
|
@ -884,4 +901,57 @@ mod tests {
|
|||
assert_eq!(r.toolchain_id, "php-8");
|
||||
assert_eq!(r.pin_origin, PinOrigin::SystemDefault);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn php_composer_json_require_dev_before_require() {
|
||||
// "require-dev" must not shadow the real "require" block even when it
|
||||
// appears first. The tightened json_line_has_key check prevents false
|
||||
// activation on the "require-dev" key.
|
||||
let dir = TempDir::new().unwrap();
|
||||
fs::write(
|
||||
dir.path().join("composer.json"),
|
||||
"{\n \"require-dev\": {\n \"php\": \"^7.0\"\n },\n \"require\": {\n \"php\": \">=8.1\"\n }\n}",
|
||||
).unwrap();
|
||||
let r = resolve_php(dir.path());
|
||||
assert_eq!(r.toolchain_id, "php-8.1");
|
||||
assert_eq!(r.pin_origin, PinOrigin::ComposerJson);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn php_composer_json_require_as_value_not_matched() {
|
||||
// "require" appearing as a string value (not a key) must not activate
|
||||
// in_require and cause a php constraint from an unrelated block to be
|
||||
// returned. Without the json_line_has_key fix, a line like
|
||||
// `"type": "require"` would set in_require=true, letting the "php"
|
||||
// key inside require-dev be matched instead of falling through.
|
||||
let dir = TempDir::new().unwrap();
|
||||
fs::write(
|
||||
dir.path().join("composer.json"),
|
||||
"{\n \"extra\": {\"type\": \"require\"},\n \"require-dev\": {\n \"php\": \"^7.0\"\n }\n}",
|
||||
).unwrap();
|
||||
let r = resolve_php(dir.path());
|
||||
// No real "require": key present — must fall back to system default.
|
||||
assert_eq!(r.pin_origin, PinOrigin::SystemDefault);
|
||||
}
|
||||
|
||||
// ── json_line_has_key unit tests ─────────────────────────────────────────
|
||||
|
||||
#[test]
|
||||
fn json_line_has_key_matches_exact_key() {
|
||||
assert!(json_line_has_key(r#" "require": {"#, "require"));
|
||||
assert!(json_line_has_key(r#"{"require": {}}"#, "require"));
|
||||
assert!(json_line_has_key(r#" "engines" : {"#, "engines"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn json_line_has_key_rejects_key_in_value() {
|
||||
assert!(!json_line_has_key(r#" "type": "require","#, "require"));
|
||||
assert!(!json_line_has_key(r#" "desc": "engines config","#, "engines"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn json_line_has_key_rejects_superstring_key() {
|
||||
// "require-dev" does not contain "require" as a quoted key.
|
||||
assert!(!json_line_has_key(r#" "require-dev": {"#, "require"));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue