Repository navigation
Resolve Maven pin properties through profiles and nesting - #2020
Mikola Lysenko (mikolalysenko) wants to merge 1 commit into
Conversation
|
Burn-down agent: merge conflict needs a decision (left unmerged, nothing pushed). This PR now conflicts with its base
Question: should this PR be rebuilt on #2005's split — keep Generated by Claude Code |
Closes the two Maven false-attestation gaps #2005 left open in VEX discovery. 1. Profile <properties> redefining a pin's property. A live <version>${v}</version> that the root <properties> resolve to the Socket pin resolves something else whenever an active profile's <properties> redefine v (or a property v names): Maven merges active profile properties over the pom's own before interpolating. Vendored mode refuses to pin over such a property (version_override); discovery attested it. PomScope now reads each profile's <properties>, and every PomDep carries version_alternatives: the other versions its build_version takes under any profile or set of profiles active together (user properties and project.* model references stay fixed; a value some set leaves unresolved, cyclic or too deep counts as the text as written). profile_override now walks live main-jar declarations too (same main_jar_declarations scope and management-governs filter): one whose build version is the pin but has an alternative off it marks the ref unattested with the existing UnattestedKind::MavenProfileUnpatched (CLI note and CLI_CONTRACT.md updated), in hosted and the pre-v5 vendored wiring alike. Profile declarations and the shared classifier check (unpatched_classifier_copy) count every alternative as a version the declaration may resolve. A <profiles> declaration's own ${v} reads its own profile's <properties> first. 2. Property versions resolved one level deep. ${a} with <a>${b}</a> now resolves through every property it names, in both views PomDep keeps: `version` (as the pom spells it: model, own profile, root properties) and `build_version` (.mvn/maven.config user properties first at every level; project.* stays the model's). Limits are the vendored reactor's: at most 16 levels, and a cycle, undefined name or unterminated ${ never resolves (the version stays as written, which is never a pin). A partly literal version (${a}.${b}-x) resolves too, and ${project.version} resolves from the model in both views. The vendored reactor's interpolator (interpolate_by and the duplicate body of Reactor::interpolate_with) moves to formats/maven as the pure interpolate_strict, built on interpolate_each, which enumerates the values a name may take (capped at 16 results). Both now detect cycles explicitly and bound work (1024 lookups, 4096 bytes), so a pom whose properties each name the next many times over fails closed instead of expanding exponentially. Reactor::interpolate drops its always-zero depth argument. Vendored behavior is otherwise unchanged. Tests (each fails before this change): - vex::discover::maven::tests::profile_properties_redefining_a_pin_property_are_not_attested - vex::discover::maven::tests::profile_declaration_reads_its_own_profile_properties - vex::discover::maven::tests::version_property_resolves_through_nested_properties (16-deep chain resolves, 17 does not; two cycles; nested user overrides) - vex::discover::maven::tests::vendored_ref_under_profile_properties_is_not_attested - formats::maven::tests::{version_properties_resolve_recursively_and_fail_closed, profile_properties_give_version_alternatives, interpolation_is_bounded} The golden corpus is unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
d7b4b40 to
ec89bd9
Compare
The base branch was force-pushed (review fixes added; MavenConfigOverride split out of profile overrides, build_version beside version, classifier handling moved into unpatched_classifier_copy). Resolved against the old base commit d7b4b40 so only this PR's changes are re-applied: - coordinate_override now runs from bypasses after profile_override, and reads build_version (as the base's live-declaration checks do) and is_executable_classifier instead of the removed list. - coordinate_alternatives reads the no-profile baseline with user properties (lookup's new build flag), matching lookup_any. - CLI_CONTRACT and the profile note keep both sides' wording. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011f9aePp9J8NPBFw7TPjhfT
Stacked on #2005, including its review fix (9765178). This closes the two Maven false-attestation gaps #2005 left open in VEX discovery.
1. Profile
<properties>redefining a pin's propertyTake a live
<version>${v}</version>whose build resolution is the Socket pin. If any profile's<properties>redefinev, or any propertyvnames, Maven resolves something else while that profile is active: it merges active profile properties over the pom's own before it interpolates. Vendored mode refuses to pin over such a property (version_override), but discovery attested it.PomScopenow reads each profile's<properties>.PomDepgainsversion_alternatives: the other versions itsbuild_versioncan take under any profile, or any set of profiles active together.project.*/pom.*model references stay fixed.resolutions(d, in_profile)helper lists every version the build may resolve for a declaration: itsbuild_version, then each alternative. It plugs into Stop attesting Maven pins a profile or user property overrides #2005's helpers in three places:unpatched_classifier_copy: live and profile classifier copies and their classifier-keyed management.profile_override, profile declarations: every version they can take is checked against the pin.profile_override, live declarations: it now also walks live main-jar declarations, with the samemain_jar_declarationsscope and management-governs filter. A declaration whosebuild_versionis the pin but has an alternative off it keeps the ref, marked unattested with the existingUnattestedKind::MavenProfileUnpatched. This applies to hosted pins and the pre-v5 vendored wiring alike. No new variant was needed; the variant doc, the CLI note text and CLI_CONTRACT.md are updated.<profiles>declaration's own${v}reads its own profile's<properties>first.2. Property versions resolved one level deep
${a}with<a>${b}</a>now resolves through every property it names, in both viewsPomDepkeeps since #2005:version(as the pom spells it, which hosted writes and rolls back): the model, then the declaration's own profile's<properties>, then the root<properties>.build_version(as the build resolves it):.mvn/maven.config-Duser properties first, at every level.project.*/pom.*stay the model's.It follows the vendored reactor's limits: at most 16 levels, and a cycle, an undefined name or an unterminated
${never resolves. The version then stays as written, which is never a pin. Partly literal versions (${a}.${b}-x) resolve too, and${project.version}resolves from the model in both views. #2005'sMavenConfigOverridecheck (spelled vs built effective versions) therefore also catches a user property that redefines a nested property.Shared interpolator
The vendored reactor's interpolator moves to
formats/maven(still pure). That covers bothinterpolate_byand the duplicate body ofReactor::interpolate_with.interpolate_strict, a single-valued wrapper overinterpolate_each.interpolate_eachenumerates every value a name can take, capped at 16 results.Reactor::interpolatedrops its depth argument, which was always zero.Tests
Each of these fails before this change:
vex::discover::maven::tests::profile_properties_redefining_a_pin_property_are_not_attestedcovers the base release, a nested property, an undefined value, a self-cycle, two profiles that move the pin only together, a managed pin, and a user property that wins over every profile.vex::discover::maven::tests::profile_declaration_reads_its_own_profile_propertiesvex::discover::maven::tests::version_property_resolves_through_nested_propertiescovers a 16-deep chain (resolves), a 17-deep chain (does not), two cycles and nested user overrides.vex::discover::maven::tests::vendored_ref_under_profile_properties_is_not_attestedformats::maven::tests::{version_properties_resolve_recursively_and_fail_closed, profile_properties_give_version_alternatives, interpolation_is_bounded}. These also assert that a nested user property movesbuild_versionbut notversion.Changed expectation after the rebase. In
version_property_resolves_through_nested_properties, the case where the pom resolves the base release and-Dp1=<pin>in.mvn/maven.configsupplies the pin through a nested property now expects no attestation. Under #2005's review fix, a Socket version that onlymaven.configsupplies is notpom.xmlwiring: hosted never writes one and rollback / remove never edit.mvn/maven.config. It is diagnosed (patched_ref_unattributable), never a ref. Nested resolution now applies that rule to nested properties too.Runs, on the rebased branch (ec89bd9):
cargo test -p socket-patch-core --lib -- vex::discover:: formats::maven vendor::jvm::passes 715.patch::redirect::together with the golden test passes 872.committed_fixture_corpus_matches_goldenpasses).cargo test -p socket-patch-cli --lib vex_sourcespasses 14.cargo clippy --locked --workspace --all-features -- -D warningsandcargo fmt --all -- --checkare clean.Not done
<groupId>/<artifactId>that is a property a profile redefines is the same class of gap; it is handled in Withhold Maven pins whose coordinates a profile redefines #2026, stacked on this branch.🤖 Generated with Claude Code