From c045c72d6d2f86e2823f7164b29d2b0ec5c49e1f Mon Sep 17 00:00:00 2001 From: bitloi <89318445+bitloi@users.noreply.github.com> Date: Fri, 20 Feb 2026 01:52:59 -0500 Subject: [PATCH] [2.x] feat: repositories_force support (#8761) The launcher (1.6.0+) sets override from repository-override and passes it via isOverrideRepositories(). No need to duplicate the file check in sbt. --- .github/workflows/ci.yml | 6 +++--- .github/workflows/nightly.yml | 2 +- build.sbt | 4 +--- launch/src/main/input_resources/sbt/sbt.boot.properties | 2 +- main/src/main/scala/sbt/Defaults.scala | 5 ++++- project/Dependencies.scala | 2 +- .../dependency-management/default-resolvers/build.sbt | 9 --------- .../dependency-management/default-resolvers/test | 1 - .../force-proxy-repos-file/build.sbt | 8 ++++++++ .../force-proxy-repos-file/global/repositories_force | 3 +++ .../force-proxy-repos-file/force-proxy-repos-file/test | 4 ++++ .../sbt/internal/scriptedtest/ScriptedLauncher.java | 8 ++++++++ .../src/main/scala/sbt/scriptedtest/ScriptedTests.scala | 5 +++++ 13 files changed, 39 insertions(+), 20 deletions(-) delete mode 100644 sbt-app/src/repo-override-test/dependency-management/default-resolvers/build.sbt delete mode 100644 sbt-app/src/repo-override-test/dependency-management/default-resolvers/test create mode 100644 sbt-app/src/repo-override-test/force-proxy-repos-file/force-proxy-repos-file/build.sbt create mode 100644 sbt-app/src/repo-override-test/force-proxy-repos-file/force-proxy-repos-file/global/repositories_force create mode 100644 sbt-app/src/repo-override-test/force-proxy-repos-file/force-proxy-repos-file/test diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1197e1aa6..db693926b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -115,7 +115,7 @@ jobs: run: | rm -rf "$HOME/.sbt/scripted/" || true rm -rf "$HOME/.ivy2/local" || true - rm -r $(find $HOME/.sbt/boot -name "*-SNAPSHOT") || true + find "$HOME/.sbt/boot" -name "*-SNAPSHOT" -exec rm -rf {} + 2>/dev/null || true - name: Publish local Zinc if: ${{ matrix.jobtype == 6 }} shell: bash @@ -160,7 +160,7 @@ jobs: if: ${{ matrix.jobtype == 4 }} shell: bash run: | - # ./sbt -v "repoOverrideTest:scripted dependency-management/*" + ./sbt -v "repoOverrideTest:scripted force-proxy-repos-file/*" ./sbt -v "scripted source-dependencies/*" - name: Build and test (5) if: ${{ matrix.jobtype == 5 }} @@ -178,7 +178,7 @@ jobs: # sbt -v -Dsbt.build.version=${BUILD_VERSION} +publishLocal # cd ../ # sbt -Dsbtzinc.path=$HOME/work/sbt/sbt/zinc -Dsbt.build.version=$BUILD_VERSION -Dsbt.build.fatal=false "+lowerUtils/publishLocal; {zinc}/publishLocal; upperModules/publishLocal" - # rm -r $(find $HOME/.sbt/boot -name "*-SNAPSHOT") || true + # find "$HOME/.sbt/boot" -name "*-SNAPSHOT" -exec rm -rf {} + 2>/dev/null || true # sbt -v -Dsbt.version=$BUILD_VERSION "++$SCALA_213; all $UTIL_TESTS; ++$SCALA_212; all $UTIL_TESTS; scripted actions/* source-dependencies/*1of3 dependency-management/*1of4 java/*" - name: Scripted (tests) if: ${{ matrix.jobtype == 7 }} diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 034c53f59..6465a3b49 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -51,7 +51,7 @@ jobs: cd ../ sbt -Dsbtzinc.path=$HOME/work/sbt/sbt/zinc -Dsbt.build.fatal=false "+lowerUtils/publish; {zinc}/publish; upperModules/publish; bundledLauncherProj/publish" rm -rf "$HOME/.ivy2/local" || true - rm -r $(find $HOME/.sbt/boot -name "*-SNAPSHOT") || true + find "$HOME/.sbt/boot" -name "*-SNAPSHOT" -exec rm -rf {} + 2>/dev/null || true find $HOME/Library/Caches/Coursier/v1 -name "ivydata-*.properties" -delete || true find $HOME/.ivy2/cache -name "ivydata-*.properties" -delete || true find $HOME/.cache/coursier/v1 -name "ivydata-*.properties" -delete || true diff --git a/build.sbt b/build.sbt index ea62bdd76..c0bae49c2 100644 --- a/build.sbt +++ b/build.sbt @@ -1044,9 +1044,7 @@ def otherRootSettings = scriptedLaunchOpts := List( "-Xmx1500M", "-Xms512M", - "-server", - "-Dsbt.override.build.repos=true", - s"""-Dsbt.repository.config=${scriptedSource.value / "repo.config"}""" + "-server" ) ::: (sys.props.get("sbt.ivy.home") match { case Some(home) => List(s"-Dsbt.ivy.home=$home") diff --git a/launch/src/main/input_resources/sbt/sbt.boot.properties b/launch/src/main/input_resources/sbt/sbt.boot.properties index 2aa284ef8..26771c66c 100644 --- a/launch/src/main/input_resources/sbt/sbt.boot.properties +++ b/launch/src/main/input_resources/sbt/sbt.boot.properties @@ -25,5 +25,5 @@ [ivy] ivy-home: ${sbt.ivy.home-${user.home}/.ivy2/} checksums: ${sbt.checksums-sha1,md5} - override-build-repos: ${sbt.override.build.repos-false} + repository-override: ${sbt.repository.override-${sbt.global.base-${user.home}/.sbt}/repositories_force} repository-config: ${sbt.repository.config-${sbt.global.base-${user.home}/.sbt}/repositories} diff --git a/main/src/main/scala/sbt/Defaults.scala b/main/src/main/scala/sbt/Defaults.scala index b24012e9c..a2500b3b1 100644 --- a/main/src/main/scala/sbt/Defaults.scala +++ b/main/src/main/scala/sbt/Defaults.scala @@ -3048,7 +3048,7 @@ object Classpaths { scmInfo.value, developers.value.toVector ), - overrideBuildResolvers := appConfiguration(isOverrideRepositories).value, + overrideBuildResolvers := appConfiguration(Classpaths.shouldOverrideBuildResolvers).value, externalResolvers := Def.uncached( ( externalResolvers.?.value, @@ -4509,6 +4509,9 @@ object Classpaths { try app.provider.scalaProvider.launcher.isOverrideRepositories catch { case _: NoSuchMethodError => false } + def shouldOverrideBuildResolvers(app: xsbti.AppConfiguration): Boolean = + isOverrideRepositories(app) || SysProp.getOrFalse("sbt.override.build.repos") + /** Loads the `appRepositories` configured for this launcher, if supported. */ def appRepositories(app: xsbti.AppConfiguration): Option[Vector[Resolver]] = try { diff --git a/project/Dependencies.scala b/project/Dependencies.scala index 4a0b33a3b..7cb1eb3e7 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -17,7 +17,7 @@ object Dependencies { private val sbtIO = "org.scala-sbt" %% "io" % ioVersion - val launcherVersion = "1.5.2" + val launcherVersion = "1.6.0" val launcherInterface = "org.scala-sbt" % "launcher-interface" % launcherVersion val rawLauncher = "org.scala-sbt" % "launcher" % launcherVersion val testInterface = "org.scala-sbt" % "test-interface" % "1.0" diff --git a/sbt-app/src/repo-override-test/dependency-management/default-resolvers/build.sbt b/sbt-app/src/repo-override-test/dependency-management/default-resolvers/build.sbt deleted file mode 100644 index ea3986b88..000000000 --- a/sbt-app/src/repo-override-test/dependency-management/default-resolvers/build.sbt +++ /dev/null @@ -1,9 +0,0 @@ -lazy val check = taskKey[Unit]("") - -lazy val root = (project in file(".")).settings( - autoScalaLibrary := false, - check := { - val ar = appResolvers.value.get - assert(!(ar exists { _.name == "public" })) - } -) diff --git a/sbt-app/src/repo-override-test/dependency-management/default-resolvers/test b/sbt-app/src/repo-override-test/dependency-management/default-resolvers/test deleted file mode 100644 index 15675b169..000000000 --- a/sbt-app/src/repo-override-test/dependency-management/default-resolvers/test +++ /dev/null @@ -1 +0,0 @@ -> check diff --git a/sbt-app/src/repo-override-test/force-proxy-repos-file/force-proxy-repos-file/build.sbt b/sbt-app/src/repo-override-test/force-proxy-repos-file/force-proxy-repos-file/build.sbt new file mode 100644 index 000000000..bcf31d002 --- /dev/null +++ b/sbt-app/src/repo-override-test/force-proxy-repos-file/force-proxy-repos-file/build.sbt @@ -0,0 +1,8 @@ +lazy val check = taskKey[Unit]("Verifies overrideBuildResolvers is true when repositories_force exists") + +lazy val root = (project in file(".")).settings( + check := { + val overrideOn = overrideBuildResolvers.value + assert(overrideOn, "overrideBuildResolvers should be true when global/repositories_force exists") + } +) diff --git a/sbt-app/src/repo-override-test/force-proxy-repos-file/force-proxy-repos-file/global/repositories_force b/sbt-app/src/repo-override-test/force-proxy-repos-file/force-proxy-repos-file/global/repositories_force new file mode 100644 index 000000000..96f1d02b8 --- /dev/null +++ b/sbt-app/src/repo-override-test/force-proxy-repos-file/force-proxy-repos-file/global/repositories_force @@ -0,0 +1,3 @@ +[repositories] + local + maven-central diff --git a/sbt-app/src/repo-override-test/force-proxy-repos-file/force-proxy-repos-file/test b/sbt-app/src/repo-override-test/force-proxy-repos-file/force-proxy-repos-file/test new file mode 100644 index 000000000..0390853fd --- /dev/null +++ b/sbt-app/src/repo-override-test/force-proxy-repos-file/force-proxy-repos-file/test @@ -0,0 +1,4 @@ +# Test for #1870: forcing proxy repos via ~/.sbt/repositories_force. +# repoOverrideTest runs with launcher; -Dsbt.global.base=/global. +# Launcher uses repository-override (repositories_force), so override is enabled. +> check diff --git a/sbt-app/src/test/scala/sbt/internal/scriptedtest/ScriptedLauncher.java b/sbt-app/src/test/scala/sbt/internal/scriptedtest/ScriptedLauncher.java index 5badb4a56..1fe4354ca 100644 --- a/sbt-app/src/test/scala/sbt/internal/scriptedtest/ScriptedLauncher.java +++ b/sbt-app/src/test/scala/sbt/internal/scriptedtest/ScriptedLauncher.java @@ -419,6 +419,14 @@ public class ScriptedLauncher { @Override public boolean isOverrideRepositories() { + try { + String globalBase = System.getProperty("sbt.global.base"); + if (globalBase != null) { + File reposForce = new File(globalBase, "repositories_force"); + return reposForce.exists(); + } + } catch (SecurityException ignored) { + } return false; } diff --git a/scripted-sbt/src/main/scala/sbt/scriptedtest/ScriptedTests.scala b/scripted-sbt/src/main/scala/sbt/scriptedtest/ScriptedTests.scala index 6d1a7d718..7d7084d5b 100644 --- a/scripted-sbt/src/main/scala/sbt/scriptedtest/ScriptedTests.scala +++ b/scripted-sbt/src/main/scala/sbt/scriptedtest/ScriptedTests.scala @@ -230,6 +230,11 @@ final class ScriptedTests( groupedTests.map { case ((group, name), originalDir) => val label = s"$group/$name" log.info(s"Running $label") + val targetGlobal = new File(tempTestDir, "global") + val reposForce = new File(targetGlobal, "repositories_force") + if (reposForce.exists()) IO.delete(reposForce) + val repos = new File(targetGlobal, "repositories") + if (repos.exists()) IO.delete(repos) // Copy test's contents and reload the sbt instance to pick them up IO.copyDirectory(originalDir, tempTestDir)