From 7409ee0c8c861ceceda16acc78391a652baf06df Mon Sep 17 00:00:00 2001 From: "Frank S. Thomas" Date: Wed, 14 Aug 2019 19:54:50 +0200 Subject: [PATCH 1/3] Add sbt temporarily as dependency This adds sbt temporarily as dependency during `getDependencies` and `getUpdatesForRepo`. This has two advantages: 1. We don't need to manually bump sbt versions when a new sbt version comes out. 2. Project and diff URLs for sbt are determined by the same mechanisms as for all other dependencies and don't need special handling (see https://github.com/fthomas/scala-steward/pull/820). Disadvantages of this approach might be: 1. We're modifying the build which could mean that it might not load after we've added the dependency. 2. Dependencies determined by Scala Steward contain "fake" dependecies. It is more than what `libraryDependencies` contains. Here is a PR created by this: https://github.com/fthomas/refined-sjs-example/pull/20 --- build.sbt | 3 +- .../org/scalasteward/core/sbt/SbtAlg.scala | 27 +++++++++++------ .../org/scalasteward/core/sbt/package.scala | 16 ---------- .../core/update/UpdateService.scala | 10 ++----- .../scalasteward/core/sbt/SbtAlgTest.scala | 30 +++++-------------- .../org/scalasteward/core/sbt/sbtTest.scala | 24 --------------- 6 files changed, 30 insertions(+), 80 deletions(-) delete mode 100644 modules/core/src/test/scala/org/scalasteward/core/sbt/sbtTest.scala diff --git a/build.sbt b/build.sbt index c54f589472..64e44bc08e 100644 --- a/build.sbt +++ b/build.sbt @@ -230,7 +230,8 @@ addCommandAlias( Seq("--whitelist", s"$home/.cache/coursier"), Seq("--whitelist", s"$home/.coursier"), Seq("--whitelist", s"$home/.ivy2"), - Seq("--whitelist", s"$home/.sbt") + Seq("--whitelist", s"$home/.sbt"), + Seq("--prune-repos=false") ).flatten.mkString(" ") } ) diff --git a/modules/core/src/main/scala/org/scalasteward/core/sbt/SbtAlg.scala b/modules/core/src/main/scala/org/scalasteward/core/sbt/SbtAlg.scala index 8c129d0fbe..cddc030247 100644 --- a/modules/core/src/main/scala/org/scalasteward/core/sbt/SbtAlg.scala +++ b/modules/core/src/main/scala/org/scalasteward/core/sbt/SbtAlg.scala @@ -17,11 +17,11 @@ package org.scalasteward.core.sbt import better.files.File +import cats.Monad import cats.implicits._ -import cats.{Functor, Monad} import io.chrisdavenport.log4cats.Logger import org.scalasteward.core.application.Config -import org.scalasteward.core.data.{Dependency, Update} +import org.scalasteward.core.data.{Dependency, Update, Version} import org.scalasteward.core.io.{FileAlg, FileData, ProcessAlg, WorkspaceAlg} import org.scalasteward.core.sbt.command._ import org.scalasteward.core.sbt.data.{ArtificialProject, SbtVersion} @@ -45,9 +45,6 @@ trait SbtAlg[F[_]] { def getUpdatesForRepo(repo: Repo): F[List[Update.Single]] def runMigrations(repo: Repo, migrations: Nel[Migration]): F[Unit] - - final def getSbtUpdate(repo: Repo)(implicit F: Functor[F]): F[Option[Update.Single]] = - getSbtVersion(repo).map(_.flatMap(findSbtUpdate)) } object SbtAlg { @@ -94,7 +91,7 @@ object SbtAlg { for { repoDir <- workspaceAlg.repoDir(repo) cmd = sbtCmd(List(libraryDependenciesAsJson, reloadPlugins, libraryDependenciesAsJson)) - lines <- exec(cmd, repoDir) + lines <- withTemporarySbtDependency(repo)(exec(cmd, repoDir)) } yield parser.parseDependencies(lines) override def getUpdatesForProject(project: ArtificialProject): F[List[Update.Single]] = @@ -121,9 +118,10 @@ object SbtAlg { maybeClearCredentials = if (config.keepCredentials) Nil else List(setCredentialsToNil) commands = maybeClearCredentials ++ List(dependencyUpdates, reloadPlugins, dependencyUpdates) - updates <- exec(sbtCmd(commands), repoDir).map(parser.parseSingleUpdates) - maybeSbtUpdate <- getSbtUpdate(repo) - } yield maybeSbtUpdate.toList ::: updates + updates <- withTemporarySbtDependency(repo) { + exec(sbtCmd(commands), repoDir).map(parser.parseSingleUpdates) + } + } yield updates override def runMigrations(repo: Repo, migrations: Nel[Migration]): F[Unit] = addGlobalPluginTemporarily(scalaStewardScalafixSbt) { @@ -162,5 +160,16 @@ object SbtAlg { } } } + + def withTemporarySbtDependency[A](repo: Repo)(fa: F[A]): F[A] = + getSbtVersion(repo).flatMap { + case Some(sbtVersion) if sbtVersion.toVersion >= Version("1.0.0") => + workspaceAlg.repoDir(repo).flatMap { repoDir => + val content = + s"""libraryDependencies += "org.scala-sbt" % "sbt" % "${sbtVersion.value}"""" + fileAlg.createTemporarily(repoDir / "project" / "tmp-sbt-dep.sbt", content)(fa) + } + case _ => fa + } } } diff --git a/modules/core/src/main/scala/org/scalasteward/core/sbt/package.scala b/modules/core/src/main/scala/org/scalasteward/core/sbt/package.scala index a950d405f1..61fe8ba49e 100644 --- a/modules/core/src/main/scala/org/scalasteward/core/sbt/package.scala +++ b/modules/core/src/main/scala/org/scalasteward/core/sbt/package.scala @@ -17,11 +17,8 @@ package org.scalasteward.core import cats.effect.{IO, Resource} -import cats.implicits._ -import org.scalasteward.core.data.Update import org.scalasteward.core.io.FileData import org.scalasteward.core.sbt.data.{SbtVersion, ScalaVersion} -import org.scalasteward.core.util.Nel import scala.io.Source package object sbt { @@ -35,19 +32,6 @@ package object sbt { val defaultScalaVersion: ScalaVersion = ScalaVersion(BuildInfo.scalaVersion) - def findNewerSbtVersion(sbtVersion: SbtVersion): Option[SbtVersion] = - (sbtVersion.value match { - case v if v.startsWith("0.13.") => Some(latestSbtVersion_0_13) - case v if v.startsWith("1.3.0-RC") => Some(SbtVersion("1.3.0-RC3")) - case v if v.startsWith("1.") => Some(defaultSbtVersion) - case _ => None - }).filter(_.toVersion > sbtVersion.toVersion) - - def findSbtUpdate(currentVersion: SbtVersion): Option[Update.Single] = - findNewerSbtVersion(currentVersion).map { newerVersion => - Update.Single("org.scala-sbt", "sbt", currentVersion.value, Nel.of(newerVersion.value)) - } - def seriesToSpecificVersion(sbtSeries: SbtVersion): SbtVersion = sbtSeries.value match { case "0.13" => latestSbtVersion_0_13 diff --git a/modules/core/src/main/scala/org/scalasteward/core/update/UpdateService.scala b/modules/core/src/main/scala/org/scalasteward/core/update/UpdateService.scala index e52fc9d050..63a54facf1 100644 --- a/modules/core/src/main/scala/org/scalasteward/core/update/UpdateService.scala +++ b/modules/core/src/main/scala/org/scalasteward/core/update/UpdateService.scala @@ -29,7 +29,7 @@ import org.scalasteward.core.update.data.UpdateState._ import org.scalasteward.core.util.MonadThrowable import org.scalasteward.core.vcs.data.PullRequestState.Closed import org.scalasteward.core.vcs.data.Repo -import org.scalasteward.core.{sbt, scalafmt, util} +import org.scalasteward.core.{scalafmt, util} final class UpdateService[F[_]]( implicit @@ -121,14 +121,10 @@ final class UpdateService[F[_]]( def findAllUpdateStates(repo: Repo, updates: List[Update.Single]): F[List[UpdateState]] = repoCacheRepository.findCache(repo).flatMap { case Some(repoCache) => - val maybeSbtUpdate = repoCache.maybeSbtVersion.flatMap(sbt.findSbtUpdate) val maybeScalafmtUpdate = repoCache.maybeScalafmtVersion.flatMap(scalafmt.findScalafmtUpdate) - val updates1 = maybeSbtUpdate.toList ++ maybeScalafmtUpdate.toList ++ updates - val maybeSbtDependency = maybeSbtUpdate.map { update => - Dependency(update.groupId, update.artifactId, update.artifactId, update.currentVersion) - } - val dependencies = maybeSbtDependency.toList ++ repoCache.dependencies + val updates1 = maybeScalafmtUpdate.toList ++ updates + val dependencies = repoCache.dependencies dependencies.traverse { dependency => findUpdateState(repo, repoCache.sha1, dependency, updates1) diff --git a/modules/core/src/test/scala/org/scalasteward/core/sbt/SbtAlgTest.scala b/modules/core/src/test/scala/org/scalasteward/core/sbt/SbtAlgTest.scala index 17b6cce95d..a805992d8d 100644 --- a/modules/core/src/test/scala/org/scalasteward/core/sbt/SbtAlgTest.scala +++ b/modules/core/src/test/scala/org/scalasteward/core/sbt/SbtAlgTest.scala @@ -2,9 +2,9 @@ package org.scalasteward.core.sbt import better.files.File import org.scalasteward.core.application.Config +import org.scalasteward.core.data.Version import org.scalasteward.core.mock.MockContext._ import org.scalasteward.core.mock.{MockContext, MockState} -import org.scalasteward.core.data.{Update, Version} import org.scalasteward.core.scalafix.Migration import org.scalasteward.core.util.Nel import org.scalasteward.core.vcs.data.Repo @@ -37,6 +37,7 @@ class SbtAlgTest extends FunSuite with Matchers { state shouldBe MockState.empty.copy( commands = Vector( + List("read", s"$repoDir/project/build.properties"), List( "TEST_VAR=GREAT", "ANOTHER_TEST_VAR=ALSO_GREAT", @@ -47,8 +48,7 @@ class SbtAlgTest extends FunSuite with Matchers { "-batch", "-no-colors", ";set every credentials := Nil;dependencyUpdates;reload plugins;dependencyUpdates" - ), - List("read", s"$repoDir/project/build.properties") + ) ) ) } @@ -63,6 +63,7 @@ class SbtAlgTest extends FunSuite with Matchers { state shouldBe MockState.empty.copy( commands = Vector( + List("read", s"$repoDir/project/build.properties"), List("rm", (repoDir / ".jvmopts").toString), List("rm", (repoDir / ".sbtopts").toString), List("create", (repoDir / ".jvmopts").toString), @@ -79,8 +80,7 @@ class SbtAlgTest extends FunSuite with Matchers { ), List("rm", (repoDir / ".jvmopts").toString), List("restore", (repoDir / ".sbtopts").toString), - List("restore", (repoDir / ".jvmopts").toString), - List("read", s"$repoDir/project/build.properties") + List("restore", (repoDir / ".jvmopts").toString) ) ) } @@ -95,6 +95,7 @@ class SbtAlgTest extends FunSuite with Matchers { state shouldBe MockState.empty.copy( commands = Vector( + List("read", s"$repoDir/project/build.properties"), List( "TEST_VAR=GREAT", "ANOTHER_TEST_VAR=ALSO_GREAT", @@ -105,8 +106,7 @@ class SbtAlgTest extends FunSuite with Matchers { "-batch", "-no-colors", ";dependencyUpdates;reload plugins;dependencyUpdates" - ), - List("read", s"$repoDir/project/build.properties") + ) ) ) } @@ -182,20 +182,4 @@ class SbtAlgTest extends FunSuite with Matchers { ) ) } - - test("getSbtUpdate") { - val repo = Repo("fthomas", "scala-steward") - val repoDir = config.workspace / repo.owner / repo.repo - val buildProperties = repoDir / "project" / "build.properties" - val initialState = MockState.empty.add(buildProperties, "sbt.version=1.2.6") - val (state, maybeUpdate) = sbtAlg.getSbtUpdate(repo).run(initialState).unsafeRunSync() - - maybeUpdate shouldBe Some( - Update.Single("org.scala-sbt", "sbt", "1.2.6", Nel.of(defaultSbtVersion.value)) - ) - state shouldBe MockState.empty.copy( - commands = Vector(List("read", s"$repoDir/project/build.properties")), - files = Map(buildProperties -> "sbt.version=1.2.6") - ) - } } diff --git a/modules/core/src/test/scala/org/scalasteward/core/sbt/sbtTest.scala b/modules/core/src/test/scala/org/scalasteward/core/sbt/sbtTest.scala deleted file mode 100644 index 98f6251ebd..0000000000 --- a/modules/core/src/test/scala/org/scalasteward/core/sbt/sbtTest.scala +++ /dev/null @@ -1,24 +0,0 @@ -package org.scalasteward.core.sbt - -import org.scalasteward.core.sbt.data.SbtVersion -import org.scalatest.{FunSuite, Matchers} -import org.scalatest.prop.TableDrivenPropertyChecks._ - -class sbtTest extends FunSuite with Matchers { - test("findNewerSbtVersion") { - val versions = Table( - ("in", "out"), - (SbtVersion("1.2.6"), Some(defaultSbtVersion)), - (SbtVersion("1.1.0"), Some(defaultSbtVersion)), - (SbtVersion("0.13.16"), Some(latestSbtVersion_0_13)), - (defaultSbtVersion, None), - (latestSbtVersion_0_13, None), - (SbtVersion("1.3.0-RC1"), Some(SbtVersion("1.3.0-RC3"))), - (SbtVersion("1.3.0-RC3"), None) - ) - - forAll(versions) { (curr: SbtVersion, maybeNewer: Option[SbtVersion]) => - findNewerSbtVersion(curr) shouldBe maybeNewer - } - } -} From c0fed5b7c722d5956665e1400baf083aed774b34 Mon Sep 17 00:00:00 2001 From: "Frank S. Thomas" Date: Wed, 14 Aug 2019 20:35:38 +0200 Subject: [PATCH 2/3] Test creation of tmp-sbt-dep.sbt --- .../main/scala/org/scalasteward/core/sbt/SbtAlg.scala | 2 +- .../main/scala/org/scalasteward/core/sbt/package.scala | 4 ++++ .../scala/org/scalasteward/core/sbt/SbtAlgTest.scala | 9 +++++++-- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/modules/core/src/main/scala/org/scalasteward/core/sbt/SbtAlg.scala b/modules/core/src/main/scala/org/scalasteward/core/sbt/SbtAlg.scala index cddc030247..46a50e8c7c 100644 --- a/modules/core/src/main/scala/org/scalasteward/core/sbt/SbtAlg.scala +++ b/modules/core/src/main/scala/org/scalasteward/core/sbt/SbtAlg.scala @@ -166,7 +166,7 @@ object SbtAlg { case Some(sbtVersion) if sbtVersion.toVersion >= Version("1.0.0") => workspaceAlg.repoDir(repo).flatMap { repoDir => val content = - s"""libraryDependencies += "org.scala-sbt" % "sbt" % "${sbtVersion.value}"""" + s"""libraryDependencies += ${sbtDependency(sbtVersion).formatAsModuleId}""" fileAlg.createTemporarily(repoDir / "project" / "tmp-sbt-dep.sbt", content)(fa) } case _ => fa diff --git a/modules/core/src/main/scala/org/scalasteward/core/sbt/package.scala b/modules/core/src/main/scala/org/scalasteward/core/sbt/package.scala index 61fe8ba49e..42d24456f4 100644 --- a/modules/core/src/main/scala/org/scalasteward/core/sbt/package.scala +++ b/modules/core/src/main/scala/org/scalasteward/core/sbt/package.scala @@ -17,6 +17,7 @@ package org.scalasteward.core import cats.effect.{IO, Resource} +import org.scalasteward.core.data.Dependency import org.scalasteward.core.io.FileData import org.scalasteward.core.sbt.data.{SbtVersion, ScalaVersion} import scala.io.Source @@ -39,6 +40,9 @@ package object sbt { case _ => defaultSbtVersion } + def sbtDependency(version: SbtVersion): Dependency = + Dependency("org.scala-sbt", "sbt", "sbt", version.value) + val scalaStewardSbt: FileData = FileData( "scala-steward.sbt", diff --git a/modules/core/src/test/scala/org/scalasteward/core/sbt/SbtAlgTest.scala b/modules/core/src/test/scala/org/scalasteward/core/sbt/SbtAlgTest.scala index a805992d8d..e5e6f8ed39 100644 --- a/modules/core/src/test/scala/org/scalasteward/core/sbt/SbtAlgTest.scala +++ b/modules/core/src/test/scala/org/scalasteward/core/sbt/SbtAlgTest.scala @@ -33,11 +33,15 @@ class SbtAlgTest extends FunSuite with Matchers { test("getUpdatesForRepo") { val repo = Repo("fthomas", "refined") val repoDir = config.workspace / "fthomas/refined" - val state = sbtAlg.getUpdatesForRepo(repo).runS(MockState.empty).unsafeRunSync() + val buildProperties = repoDir / "project" / "build.properties" + val initialState = MockState.empty.copy(files = Map(buildProperties -> "sbt.version=1.2.6")) + val state = sbtAlg.getUpdatesForRepo(repo).runS(initialState).unsafeRunSync() state shouldBe MockState.empty.copy( + files = Map(buildProperties -> "sbt.version=1.2.6"), commands = Vector( List("read", s"$repoDir/project/build.properties"), + List("create", s"$repoDir/project/tmp-sbt-dep.sbt"), List( "TEST_VAR=GREAT", "ANOTHER_TEST_VAR=ALSO_GREAT", @@ -48,7 +52,8 @@ class SbtAlgTest extends FunSuite with Matchers { "-batch", "-no-colors", ";set every credentials := Nil;dependencyUpdates;reload plugins;dependencyUpdates" - ) + ), + List("rm", s"$repoDir/project/tmp-sbt-dep.sbt") ) ) } From ace1a4d74f8a09a6157f0f4107217c38fd036e46 Mon Sep 17 00:00:00 2001 From: "Frank S. Thomas" Date: Wed, 14 Aug 2019 21:49:55 +0200 Subject: [PATCH 3/3] Use withTemporarySbtDependency only in getUpdates --- .../scala/org/scalasteward/core/sbt/SbtAlg.scala | 15 ++++++++------- .../scala/org/scalasteward/core/sbt/package.scala | 10 +++++++--- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/modules/core/src/main/scala/org/scalasteward/core/sbt/SbtAlg.scala b/modules/core/src/main/scala/org/scalasteward/core/sbt/SbtAlg.scala index 46a50e8c7c..7892af4c80 100644 --- a/modules/core/src/main/scala/org/scalasteward/core/sbt/SbtAlg.scala +++ b/modules/core/src/main/scala/org/scalasteward/core/sbt/SbtAlg.scala @@ -21,7 +21,7 @@ import cats.Monad import cats.implicits._ import io.chrisdavenport.log4cats.Logger import org.scalasteward.core.application.Config -import org.scalasteward.core.data.{Dependency, Update, Version} +import org.scalasteward.core.data.{Dependency, Update} import org.scalasteward.core.io.{FileAlg, FileData, ProcessAlg, WorkspaceAlg} import org.scalasteward.core.sbt.command._ import org.scalasteward.core.sbt.data.{ArtificialProject, SbtVersion} @@ -91,8 +91,10 @@ object SbtAlg { for { repoDir <- workspaceAlg.repoDir(repo) cmd = sbtCmd(List(libraryDependenciesAsJson, reloadPlugins, libraryDependenciesAsJson)) - lines <- withTemporarySbtDependency(repo)(exec(cmd, repoDir)) - } yield parser.parseDependencies(lines) + lines <- exec(cmd, repoDir) + maybeSbtVersion <- getSbtVersion(repo) + maybeSbtDependency = maybeSbtVersion.flatMap(sbtDependency) + } yield maybeSbtDependency.toList ++ parser.parseDependencies(lines) override def getUpdatesForProject(project: ArtificialProject): F[List[Update.Single]] = for { @@ -163,13 +165,12 @@ object SbtAlg { def withTemporarySbtDependency[A](repo: Repo)(fa: F[A]): F[A] = getSbtVersion(repo).flatMap { - case Some(sbtVersion) if sbtVersion.toVersion >= Version("1.0.0") => + _.flatMap(sbtDependency).fold(fa) { dependency => workspaceAlg.repoDir(repo).flatMap { repoDir => - val content = - s"""libraryDependencies += ${sbtDependency(sbtVersion).formatAsModuleId}""" + val content = s"libraryDependencies += ${dependency.formatAsModuleId}" fileAlg.createTemporarily(repoDir / "project" / "tmp-sbt-dep.sbt", content)(fa) } - case _ => fa + } } } } diff --git a/modules/core/src/main/scala/org/scalasteward/core/sbt/package.scala b/modules/core/src/main/scala/org/scalasteward/core/sbt/package.scala index 42d24456f4..d401a19911 100644 --- a/modules/core/src/main/scala/org/scalasteward/core/sbt/package.scala +++ b/modules/core/src/main/scala/org/scalasteward/core/sbt/package.scala @@ -16,8 +16,9 @@ package org.scalasteward.core +import cats.implicits._ import cats.effect.{IO, Resource} -import org.scalasteward.core.data.Dependency +import org.scalasteward.core.data.{Dependency, Version} import org.scalasteward.core.io.FileData import org.scalasteward.core.sbt.data.{SbtVersion, ScalaVersion} import scala.io.Source @@ -40,8 +41,11 @@ package object sbt { case _ => defaultSbtVersion } - def sbtDependency(version: SbtVersion): Dependency = - Dependency("org.scala-sbt", "sbt", "sbt", version.value) + def sbtDependency(sbtVersion: SbtVersion): Option[Dependency] = + if (sbtVersion.toVersion >= Version("1.0.0")) + Some(Dependency("org.scala-sbt", "sbt", "sbt", sbtVersion.value)) + else + None val scalaStewardSbt: FileData = FileData(