Skip to content

Commit

Permalink
Try using sbt-scalafix for Scalafix build migrations
Browse files Browse the repository at this point in the history
  • Loading branch information
DavidGregory084 committed Jul 31, 2023
1 parent ea94b76 commit cf82b87
Show file tree
Hide file tree
Showing 2 changed files with 225 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,15 @@ import org.scalasteward.core.buildtool.sbt.command._
import org.scalasteward.core.buildtool.{BuildRoot, BuildToolAlg}
import org.scalasteward.core.coursier.VersionsCache
import org.scalasteward.core.data.{Dependency, Scope, Version}
import org.scalasteward.core.edit.scalafix.{ScalafixCli, ScalafixMigration}
import org.scalasteward.core.edit.scalafix.ScalafixMigration
import org.scalasteward.core.io.process.SlurpOptions
import org.scalasteward.core.io.{FileAlg, FileData, ProcessAlg, WorkspaceAlg}
import org.scalasteward.core.util.Nel
import org.scalasteward.core.buildtool.sbt.scalaStewardSbtScalafix

final class SbtAlg[F[_]](config: Config)(implicit
fileAlg: FileAlg[F],
processAlg: ProcessAlg[F],
scalafixCli: ScalafixCli[F],
workspaceAlg: WorkspaceAlg[F],
versionsCache: VersionsCache[F],
F: Concurrent[F]
Expand Down Expand Up @@ -129,18 +129,52 @@ final class SbtAlg[F[_]](config: Config)(implicit
.getVersions(Scope(sbtScalafixDependency, List(config.defaultResolver)), None)
.map(_.lastOption)

private def addScalafixPluginTemporarily(
buildRootDir: File,
pluginVersion: Version,
metaBuilds: Int
): Resource[F, Unit] = {
val plugin = scalaStewardSbtScalafix(pluginVersion)
List
.iterate(buildRootDir / project / project, metaBuilds + 1)(_ / project)
.collectFold(fileAlg.createTemporarily(_, plugin))
}

private def addScalacOptionsTemporarily(
buildRootDir: File,
scalacOptions: Option[Nel[String]],
metaBuilds: Int
): Resource[F, Unit] =
scalacOptions.fold(Resource.unit[F]) { opts =>
val options = scalaStewardScalafixOptions(opts.toList)
List
.iterate(buildRootDir / project, metaBuilds + 1)(_ / project)
.collectFold(fileAlg.createTemporarily(_, options))
}

private def runBuildMigration(buildRoot: BuildRoot, migration: ScalafixMigration): F[Unit] =
for {
buildRootDir <- workspaceAlg.buildRootDir(buildRoot)
projectDir = buildRootDir / project
files0 <- (
fileAlg.walk(buildRootDir, 1).filter(_.extension.contains(".sbt")) ++
fileAlg.walk(projectDir, 3).filter(_.extension.exists(Set(".sbt", ".scala")))
).compile.toList
_ <- Nel.fromList(files0).fold(F.unit) { files1 =>
scalafixCli.runMigration(buildRootDir, files1, migration)
}
} yield ()
OptionT(latestSbtScalafixVersion).foreachF { pluginVersion =>
for {
buildRootDir <- workspaceAlg.buildRootDir(buildRoot)
metaBuilds <- metaBuildsCount(buildRootDir)
_ <- addScalafixPluginTemporarily(buildRootDir, pluginVersion, metaBuilds).surround {
addScalacOptionsTemporarily(buildRootDir, migration.scalacOptions, metaBuilds).surround {
val scalafixCmds = migration.rewriteRules.map(rule => s"$scalafixAll $rule").toList
val slurpOptions = SlurpOptions.ignoreBufferOverflow
val commands = Nel.fromList(
List.fill(metaBuilds + 1)(List(reloadPlugins, scalafixEnable) ++ scalafixCmds).flatten
)
commands.fold(F.unit) { cmds =>
sbt(
cmds,
buildRootDir,
slurpOptions
).void
}
}
}
} yield ()
}

private def sbt(
sbtCommands: Nel[String],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,184 @@ class SbtAlgTest extends FunSuite {
assertEquals(state, expected)
}

test("runMigrations: build migration") {
val repo = Repo("sbt-alg", "test-build-migration-1")
val buildRoot = BuildRoot(repo, ".")
val repoDir = workspaceAlg.repoDir(repo).unsafeRunSync()
val migration = ScalafixMigration(
groupId = GroupId("io.github.davidgregory084"),
artifactIds = Nel.of("sbt-tpolecat"),
newVersion = Version("0.5.0"),
rewriteRules = Nel.of("github:typelevel/sbt-tpolecat/v0_5?sha=v0.5.0"),
target = Some(ScalafixMigration.Target.Build)
)
val initialState = MockState.empty
.addFiles(
workspace / s"store/versions/v2/https/repo1.maven.org/maven2/ch/epfl/scala/sbt-scalafix_2.12_1.0/versions.json" -> sbtScalafixVersionJson
)
.unsafeRunSync()
val state = sbtAlg.runMigration(buildRoot, migration).runS(initialState).unsafeRunSync()
val expected = initialState.copy(
trace = Vector(
Cmd(
"read",
s"$workspace/store/versions/v2/https/repo1.maven.org/maven2/ch/epfl/scala/sbt-scalafix_2.12_1.0/versions.json"
),
Cmd("test", "-d", s"$repoDir/project"),
Cmd("write", s"$repoDir/project/project/scala-steward-sbt-scalafix.sbt"),
Cmd.execSandboxed(
repoDir,
"sbt",
"-Dsbt.color=false",
"-Dsbt.log.noformat=true",
"-Dsbt.supershell=false",
"-Dsbt.server.forcestart=true",
s";$reloadPlugins;$scalafixEnable;$scalafixAll github:typelevel/sbt-tpolecat/v0_5?sha=v0.5.0"
),
Cmd("rm", "-rf", s"$repoDir/project/project/scala-steward-sbt-scalafix.sbt")
)
)
assertEquals(state, expected)
}

test("runMigrations: build migration with meta-build") {
val repo = Repo("sbt-alg", "test-build-migration-2")
val buildRoot = BuildRoot(repo, ".")
val repoDir = workspaceAlg.repoDir(repo).unsafeRunSync()
val migration = ScalafixMigration(
groupId = GroupId("io.github.davidgregory084"),
artifactIds = Nel.of("sbt-tpolecat"),
newVersion = Version("0.5.0"),
rewriteRules = Nel.of("github:typelevel/sbt-tpolecat/v0_5?sha=v0.5.0"),
target = Some(ScalafixMigration.Target.Build)
)
val initialState = MockState.empty
.addFiles(
repoDir / "project" / "Dependencies.scala" -> "object Dependencies", // put anything at all into the meta-build
workspace / s"store/versions/v2/https/repo1.maven.org/maven2/ch/epfl/scala/sbt-scalafix_2.12_1.0/versions.json" -> sbtScalafixVersionJson
)
.unsafeRunSync()
val state = sbtAlg.runMigration(buildRoot, migration).runS(initialState).unsafeRunSync()
val expected = initialState.copy(
trace = Vector(
Cmd(
"read",
s"$workspace/store/versions/v2/https/repo1.maven.org/maven2/ch/epfl/scala/sbt-scalafix_2.12_1.0/versions.json"
),
Cmd("test", "-d", s"$repoDir/project"),
Cmd("test", "-d", s"$repoDir/project/project"),
Cmd("write", s"$repoDir/project/project/scala-steward-sbt-scalafix.sbt"),
Cmd("write", s"$repoDir/project/project/project/scala-steward-sbt-scalafix.sbt"),
Cmd.execSandboxed(
repoDir,
"sbt",
"-Dsbt.color=false",
"-Dsbt.log.noformat=true",
"-Dsbt.supershell=false",
"-Dsbt.server.forcestart=true",
s";$reloadPlugins;$scalafixEnable;$scalafixAll github:typelevel/sbt-tpolecat/v0_5?sha=v0.5.0" +
s";$reloadPlugins;$scalafixEnable;$scalafixAll github:typelevel/sbt-tpolecat/v0_5?sha=v0.5.0"
),
Cmd("rm", "-rf", s"$repoDir/project/project/project/scala-steward-sbt-scalafix.sbt"),
Cmd("rm", "-rf", s"$repoDir/project/project/scala-steward-sbt-scalafix.sbt")
)
)
assertEquals(state, expected)
}

test("runMigrations: build migration with scalacOptions") {
val repo = Repo("sbt-alg", "test-build-migration-3")
val buildRoot = BuildRoot(repo, ".")
val repoDir = workspaceAlg.repoDir(repo).unsafeRunSync()
val migration = ScalafixMigration(
groupId = GroupId("io.github.davidgregory084"),
artifactIds = Nel.of("sbt-tpolecat"),
newVersion = Version("0.5.0"),
rewriteRules = Nel.of("github:typelevel/sbt-tpolecat/v0_5?sha=v0.5.0"),
scalacOptions = Some(Nel.of("-P:semanticdb:synthetics:on")),
target = Some(ScalafixMigration.Target.Build)
)
val initialState = MockState.empty
.addFiles(
workspace / s"store/versions/v2/https/repo1.maven.org/maven2/ch/epfl/scala/sbt-scalafix_2.12_1.0/versions.json" -> sbtScalafixVersionJson
)
.unsafeRunSync()
val state = sbtAlg.runMigration(buildRoot, migration).runS(initialState).unsafeRunSync()
val expected = initialState.copy(
trace = Vector(
Cmd(
"read",
s"$workspace/store/versions/v2/https/repo1.maven.org/maven2/ch/epfl/scala/sbt-scalafix_2.12_1.0/versions.json"
),
Cmd("test", "-d", s"$repoDir/project"),
Cmd("write", s"$repoDir/project/project/scala-steward-sbt-scalafix.sbt"),
Cmd("write", s"$repoDir/project/scala-steward-scalafix-options.sbt"),
Cmd.execSandboxed(
repoDir,
"sbt",
"-Dsbt.color=false",
"-Dsbt.log.noformat=true",
"-Dsbt.supershell=false",
"-Dsbt.server.forcestart=true",
s";$reloadPlugins;$scalafixEnable;$scalafixAll github:typelevel/sbt-tpolecat/v0_5?sha=v0.5.0"
),
Cmd("rm", "-rf", s"$repoDir/project/scala-steward-scalafix-options.sbt"),
Cmd("rm", "-rf", s"$repoDir/project/project/scala-steward-sbt-scalafix.sbt")
)
)
assertEquals(state, expected)
}

test("runMigrations: build migration with scalacOptions and meta-build") {
val repo = Repo("sbt-alg", "test-build-migration-4")
val buildRoot = BuildRoot(repo, ".")
val repoDir = workspaceAlg.repoDir(repo).unsafeRunSync()
val migration = ScalafixMigration(
groupId = GroupId("io.github.davidgregory084"),
artifactIds = Nel.of("sbt-tpolecat"),
newVersion = Version("0.5.0"),
rewriteRules = Nel.of("github:typelevel/sbt-tpolecat/v0_5?sha=v0.5.0"),
scalacOptions = Some(Nel.of("-P:semanticdb:synthetics:on")),
target = Some(ScalafixMigration.Target.Build)
)
val initialState = MockState.empty
.addFiles(
repoDir / "project" / "Dependencies.scala" -> "object Dependencies", // put anything at all into the meta-build
workspace / s"store/versions/v2/https/repo1.maven.org/maven2/ch/epfl/scala/sbt-scalafix_2.12_1.0/versions.json" -> sbtScalafixVersionJson
)
.unsafeRunSync()
val state = sbtAlg.runMigration(buildRoot, migration).runS(initialState).unsafeRunSync()
val expected = initialState.copy(
trace = Vector(
Cmd(
"read",
s"$workspace/store/versions/v2/https/repo1.maven.org/maven2/ch/epfl/scala/sbt-scalafix_2.12_1.0/versions.json"
),
Cmd("test", "-d", s"$repoDir/project"),
Cmd("test", "-d", s"$repoDir/project/project"),
Cmd("write", s"$repoDir/project/project/scala-steward-sbt-scalafix.sbt"),
Cmd("write", s"$repoDir/project/project/project/scala-steward-sbt-scalafix.sbt"),
Cmd("write", s"$repoDir/project/scala-steward-scalafix-options.sbt"),
Cmd("write", s"$repoDir/project/project/scala-steward-scalafix-options.sbt"),
Cmd.execSandboxed(
repoDir,
"sbt",
"-Dsbt.color=false",
"-Dsbt.log.noformat=true",
"-Dsbt.supershell=false",
"-Dsbt.server.forcestart=true",
s";$reloadPlugins;$scalafixEnable;$scalafixAll github:typelevel/sbt-tpolecat/v0_5?sha=v0.5.0" +
s";$reloadPlugins;$scalafixEnable;$scalafixAll github:typelevel/sbt-tpolecat/v0_5?sha=v0.5.0"
),
Cmd("rm", "-rf", s"$repoDir/project/project/scala-steward-scalafix-options.sbt"),
Cmd("rm", "-rf", s"$repoDir/project/scala-steward-scalafix-options.sbt"),
Cmd("rm", "-rf", s"$repoDir/project/project/project/scala-steward-sbt-scalafix.sbt"),
Cmd("rm", "-rf", s"$repoDir/project/project/scala-steward-sbt-scalafix.sbt")
)
)
assertEquals(state, expected)
}

private def sbtScalafixVersionJson =
s"""|{
| "updatedAt" : 9999999999999,
Expand Down

0 comments on commit cf82b87

Please sign in to comment.