Skip to content

Commit d2f29a5

Browse files
committed
Weigh every module before skipping the Maven root pin
external_management returned Ok(None) as soon as one module's inherited parent or imported BOM resolved the base version, so a later module that imports its own BOM (or sets its own property) at another version was never checked. The root pin then overrode that module's management and reintroduced the #488 downgrade. Continue to the next module instead and only clear the root once every module agrees. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KoEk4Y9wedBsjtt9kTUPVY
1 parent 13411d7 commit d2f29a5

1 file changed

Lines changed: 49 additions & 3 deletions

File tree

‎crates/socket-patch-core/src/vendor/jvm/maven_reactor.rs‎

Lines changed: 49 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -782,7 +782,11 @@ impl Reactor {
782782
) -> Result<Option<ManagedConflict>, Missing> {
783783
let (g, a) = (patch.group_id, patch.artifact_id);
784784
let ext_chain = self.external_chain(root, lookup)?;
785-
for rel in self.scope.iter().filter(|rel| self.local_root(rel) == root) {
785+
// Every module under this root must agree: one module whose
786+
// management already resolves the base version says nothing about
787+
// the next, which may interpolate a different one the root pin would
788+
// override.
789+
'modules: for rel in self.scope.iter().filter(|rel| self.local_root(rel) == root) {
786790
let locally_versioned = self.chain(rel).any(|p| {
787791
let doc = &self.poms[p].doc;
788792
doc.keyed_declarations(g, a)
@@ -822,7 +826,7 @@ impl Reactor {
822826
// overridden by management, so a pin cannot reach it
823827
// even at the base version.
824828
if managed && is_base_like(&v, patch.version) {
825-
return Ok(None);
829+
continue 'modules;
826830
}
827831
let how = if managed {
828832
"managed by"
@@ -866,7 +870,7 @@ impl Reactor {
866870
let mut seen = BTreeSet::new();
867871
if let Some(v) = bom_manages(bom, g, a, lookup, &mut seen, 0)? {
868872
if is_base_like(&v, patch.version) {
869-
return Ok(None);
873+
continue 'modules;
870874
}
871875
let (bg, ba, bv) = bom;
872876
return Ok(Some(ManagedConflict {
@@ -3123,6 +3127,48 @@ mod tests {
31233127
);
31243128
}
31253129

3130+
#[test]
3131+
fn a_later_module_importing_another_version_leaves_the_root_unpinned() {
3132+
// Module `a` sees the root's BOM at the base version; module `b`
3133+
// imports its own BOM managing another one. A root pin would
3134+
// override `b`'s management, so one agreeing module is not enough.
3135+
let mut files = external_reactor(
3136+
"<properties><bom.version>1</bom.version></properties>",
3137+
IMPORT_BOM,
3138+
);
3139+
let root = text(&files, "pom.xml")
3140+
.replace("<module>a</module>", "<module>a</module><module>b</module>");
3141+
files.insert("pom.xml".into(), root.into_bytes());
3142+
let b = "<project>\n <modelVersion>4.0.0</modelVersion>\n <parent>\n \
3143+
<groupId>com.example</groupId>\n <artifactId>root</artifactId>\n \
3144+
<version>1.0.0</version>\n </parent>\n <artifactId>b</artifactId>\n \
3145+
<dependencyManagement><dependencies><dependency>\
3146+
<groupId>com.corp</groupId><artifactId>corp-bom</artifactId><version>2</version>\
3147+
<type>pom</type><scope>import</scope></dependency></dependencies>\
3148+
</dependencyManagement>\n \
3149+
<dependencies>\n <dependency><groupId>org.apache.commons</groupId>\
3150+
<artifactId>commons-text</artifactId></dependency>\n </dependencies>\n\
3151+
</project>\n";
3152+
files.insert("b/pom.xml".into(), b.as_bytes().to_vec());
3153+
let repo = ExternalPoms::from([
3154+
(
3155+
corp("corp-bom", "1"),
3156+
Some(bom("corp-bom", "1", &dep("1.10.0"))),
3157+
),
3158+
(
3159+
corp("corp-bom", "2"),
3160+
Some(bom("corp-bom", "2", &dep("1.11.0"))),
3161+
),
3162+
]);
3163+
let plan = run_external(&files, &repo).0.unwrap();
3164+
assert!(
3165+
reasons(&plan).contains(&"conflicting_managed_version".to_string()),
3166+
"{:?}",
3167+
plan.warnings
3168+
);
3169+
assert!(!root_pinned(&plan, &files), "the root must not be pinned");
3170+
}
3171+
31263172
#[test]
31273173
fn a_nested_bom_import_is_followed() {
31283174
let files = external_reactor(

0 commit comments

Comments
 (0)