From 594cef08e8b4d88088d4d3d5b10038a7c3656107 Mon Sep 17 00:00:00 2001 From: Luis Bianchin Date: Mon, 13 Apr 2026 16:37:42 +0200 Subject: [PATCH] Use settings.xml repositories for parent POM resolution The repositories parameter in loadEffectivePom was accepted but ignored. MavenModelResolver was constructed once at class level with only Maven Central, so parent POMs hosted on custom repos (Nexus, Artifactory, etc.) could not be resolved. Wire repositories from Maven settings.xml active profiles into MavenModelResolver by extracting them as Aether RemoteRepository objects and passing them through the loadEffectivePom call chain. Also construct MavenModelResolver per-call instead of sharing a single mutable instance, preventing repository state from leaking across calls. Fixes https://github.com/sbt/sbt-pom-reader/issues/72 --- src/main/scala/sbtpomreader/MavenHelper.scala | 18 ++++++++++++------ .../scala/sbtpomreader/MavenPomResolver.scala | 14 +++++--------- .../sbtpomreader/MavenUserSettingsHelper.scala | 11 +++++++++++ src/main/scala/sbtpomreader/package.scala | 5 +++-- .../can-read-settings-repos/build.sbt | 9 +++++++-- 5 files changed, 38 insertions(+), 19 deletions(-) diff --git a/src/main/scala/sbtpomreader/MavenHelper.scala b/src/main/scala/sbtpomreader/MavenHelper.scala index 65b1290..fb9b4c5 100644 --- a/src/main/scala/sbtpomreader/MavenHelper.scala +++ b/src/main/scala/sbtpomreader/MavenHelper.scala @@ -30,12 +30,18 @@ object MavenHelper { mvnLocalRepository := defaultLocalRepo, profiles := Seq.empty, mavenUserProperties := Map.empty, - effectivePom := loadEffectivePom( - pomLocation.value, - mvnLocalRepository.value, - profiles.value, - mavenUserProperties.value - ), + effectivePom := { + val settingsRepos = effectiveSettings.value + .map(MavenUserSettingsHelper.getUserRemoteRepositories) + .getOrElse(Seq.empty) + loadEffectivePom( + pomLocation.value, + mvnLocalRepository.value, + profiles.value, + mavenUserProperties.value, + settingsRepos + ) + }, effectiveSettings := loadUserSettings(settingsLocation.value, profiles.value), showEffectivePom := showPom(pomLocation.value, effectivePom.value, streams.value), isJavaOnly := false diff --git a/src/main/scala/sbtpomreader/MavenPomResolver.scala b/src/main/scala/sbtpomreader/MavenPomResolver.scala index 7ceb2b9..386cd22 100644 --- a/src/main/scala/sbtpomreader/MavenPomResolver.scala +++ b/src/main/scala/sbtpomreader/MavenPomResolver.scala @@ -32,15 +32,6 @@ class MavenPomResolver(system: RepositorySystem, localRepo: File) { new RemoteRepository.Builder("central", "default", "https://repo.maven.apache.org/maven2").build() ) - // TODO - Add repositories from the pom... - val modelResolver: ModelResolver = { - new MavenModelResolver( - session, - system, - repositories = defaultRepositories - ) - } - def loadEffectivePom( pomFile: File, repositories: Seq[RemoteRepository], @@ -48,6 +39,11 @@ class MavenPomResolver(system: RepositorySystem, localRepo: File) { userPropsMap: Map[String, String] ): Model = try { + val modelResolver: ModelResolver = new MavenModelResolver( + session, + system, + repositories = defaultRepositories ++ repositories + ) val userProperties = new java.util.Properties() userPropsMap.foreach(kv => userProperties.put(kv._1, kv._2)) val request = new DefaultModelBuildingRequest diff --git a/src/main/scala/sbtpomreader/MavenUserSettingsHelper.scala b/src/main/scala/sbtpomreader/MavenUserSettingsHelper.scala index 613bcc1..3dd6307 100644 --- a/src/main/scala/sbtpomreader/MavenUserSettingsHelper.scala +++ b/src/main/scala/sbtpomreader/MavenUserSettingsHelper.scala @@ -7,6 +7,7 @@ import scala.collection.JavaConverters.* import org.apache.maven.model.{ Model as PomModel, Repository as PomRepository } import org.apache.maven.settings.Settings as MavenSettings import org.apache.maven.settings.building.{ DefaultSettingsBuilderFactory, DefaultSettingsBuildingRequest } +import org.eclipse.aether.repository.RemoteRepository /** * Helper object with functions to extract settings from the user's Maven settings file (typically ~/.m2/settings.xml) @@ -38,6 +39,16 @@ object MavenUserSettingsHelper { } yield repo.getId at repo.getUrl } + /** Extract repositories from user settings as Aether RemoteRepository objects for POM resolution. */ + def getUserRemoteRepositories(settings: MavenSettings): Seq[RemoteRepository] = { + val profiles = settings.getProfilesAsMap + for { + profileName <- settings.getActiveProfiles.asScala + profile <- Option(profiles.get(profileName)).toSeq + repo <- profile.getRepositories.asScala + } yield new RemoteRepository.Builder(repo.getId, repo.getLayout, repo.getUrl).build() + } + /** Extract the server credentials from the given settings file. */ def serverCredentials(settings: MavenSettings): Seq[ServerCredentials] = for { diff --git a/src/main/scala/sbtpomreader/package.scala b/src/main/scala/sbtpomreader/package.scala index 1d40c0e..13eb1a5 100644 --- a/src/main/scala/sbtpomreader/package.scala +++ b/src/main/scala/sbtpomreader/package.scala @@ -26,7 +26,8 @@ package object sbtpomreader { pom: File, localRepo: File = defaultLocalRepo, profiles: Seq[String], - userProps: Map[String, String] + userProps: Map[String, String], + additionalRepositories: Seq[org.eclipse.aether.repository.RemoteRepository] = Seq.empty ) = - MavenPomResolver(localRepo).loadEffectivePom(pom, Seq.empty, profiles, userProps) + MavenPomResolver(localRepo).loadEffectivePom(pom, additionalRepositories, profiles, userProps) } diff --git a/src/sbt-test/simple-pom/can-read-settings-repos/build.sbt b/src/sbt-test/simple-pom/can-read-settings-repos/build.sbt index 182d7d2..3386a7d 100644 --- a/src/sbt-test/simple-pom/can-read-settings-repos/build.sbt +++ b/src/sbt-test/simple-pom/can-read-settings-repos/build.sbt @@ -5,6 +5,11 @@ TaskKey[Unit]("checkSettings") := { val extracted = Project extract state.value val rez = extracted.get(resolvers) // Should only pick up one of the two repositories due to profile activation. - assert(rez.exists(_.name == "sbt-bintray")) - assert(!rez.exists(_.name == "one-sad-repo")) + assert(rez.exists(_.name == "sbt-bintray"), "Expected sbt-bintray in resolvers, found: " + rez) + assert(!rez.exists(_.name == "one-sad-repo"), "Unexpected one-sad-repo in resolvers") + + // Verify effective POM loaded successfully with settings repos wired in. + val pom = extracted.get(effectivePom) + assert(pom != null, "effectivePom should be loaded") + assert(pom.getGroupId == "com.jsuereth.junk", "Expected groupId com.jsuereth.junk, found: " + pom.getGroupId) }