Skip to content

Commit 878f5b1

Browse files
authored
Merge pull request #2852 from scala-steward-org/topic/add-steward-plugin-locally
Add sbt plugins locally and not globally
2 parents c81ab90 + 1228534 commit 878f5b1

File tree

9 files changed

+79
-104
lines changed

9 files changed

+79
-104
lines changed

modules/core/src/main/scala/org/scalasteward/core/application/StewardAlg.scala

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ import better.files.File
2020
import cats.effect.{ExitCode, Sync}
2121
import cats.syntax.all._
2222
import fs2.Stream
23-
import org.scalasteward.core.buildtool.sbt.SbtAlg
2423
import org.scalasteward.core.git.GitAlg
2524
import org.scalasteward.core.io.{FileAlg, WorkspaceAlg}
2625
import org.scalasteward.core.nurture.NurtureAlg
@@ -44,7 +43,6 @@ final class StewardAlg[F[_]](config: Config)(implicit
4443
nurtureAlg: NurtureAlg[F],
4544
pruningAlg: PruningAlg[F],
4645
repoCacheAlg: RepoCacheAlg[F],
47-
sbtAlg: SbtAlg[F],
4846
selfCheckAlg: SelfCheckAlg[F],
4947
workspaceAlg: WorkspaceAlg[F],
5048
F: Sync[F]
@@ -95,7 +93,7 @@ final class StewardAlg[F[_]](config: Config)(implicit
9593
for {
9694
_ <- selfCheckAlg.checkAll
9795
_ <- workspaceAlg.cleanWorkspace
98-
exitCode <- sbtAlg.addGlobalPlugins.surround {
96+
exitCode <-
9997
(config.githubApp.map(getGitHubAppRepos).getOrElse(Stream.empty) ++
10098
readRepos(config.reposFile))
10199
.evalMap(steward)
@@ -109,7 +107,6 @@ final class StewardAlg[F[_]](config: Config)(implicit
109107
s"""The format is "- $$owner/$$repo" or "- $$owner/$$repo:$$branch"."""
110108
logger.warn(msg).as(ExitCode.Success)
111109
}
112-
}
113110
} yield exitCode
114111
}
115112
}

modules/core/src/main/scala/org/scalasteward/core/buildtool/sbt/SbtAlg.scala

Lines changed: 35 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,14 @@ import org.scalasteward.core.buildtool.BuildToolAlg
2525
import org.scalasteward.core.buildtool.sbt.command._
2626
import org.scalasteward.core.buildtool.sbt.data.SbtVersion
2727
import org.scalasteward.core.coursier.VersionsCache
28-
import org.scalasteward.core.data.{Dependency, Scope}
28+
import org.scalasteward.core.data.{Dependency, Scope, Version}
2929
import org.scalasteward.core.edit.scalafix.{ScalafixCli, ScalafixMigration}
30-
import org.scalasteward.core.io.{FileAlg, FileData, ProcessAlg, WorkspaceAlg}
30+
import org.scalasteward.core.io.{FileAlg, ProcessAlg, WorkspaceAlg}
3131
import org.scalasteward.core.util.Nel
3232
import org.scalasteward.core.vcs.data.BuildRoot
33-
import org.typelevel.log4cats.Logger
3433

3534
final class SbtAlg[F[_]](config: Config)(implicit
3635
fileAlg: FileAlg[F],
37-
logger: Logger[F],
3836
processAlg: ProcessAlg[F],
3937
scalafixCli: ScalafixCli[F],
4038
workspaceAlg: WorkspaceAlg[F],
@@ -44,17 +42,6 @@ final class SbtAlg[F[_]](config: Config)(implicit
4442
private def getSbtDependency(buildRoot: BuildRoot): F[Option[Dependency]] =
4543
OptionT(getSbtVersion(buildRoot)).subflatMap(sbtDependency).value
4644

47-
private def addGlobalPluginTemporarily(plugin: FileData): Resource[F, Unit] =
48-
Resource.eval(sbtDir).flatMap { dir =>
49-
List("0.13", "1.0").traverse_ { version =>
50-
fileAlg.createTemporarily(dir / version / "plugins" / plugin.name, plugin.content)
51-
}
52-
}
53-
54-
def addGlobalPlugins: Resource[F, Unit] =
55-
Resource.eval(logger.info("Add global sbt plugins")) >>
56-
Resource.eval(stewardPlugin).flatMap(addGlobalPluginTemporarily)
57-
5845
override def containsBuild(buildRoot: BuildRoot): F[Boolean] =
5946
workspaceAlg
6047
.buildRootDir(buildRoot)
@@ -63,18 +50,28 @@ final class SbtAlg[F[_]](config: Config)(implicit
6350
private def getSbtVersion(buildRoot: BuildRoot): F[Option[SbtVersion]] =
6451
for {
6552
buildRootDir <- workspaceAlg.buildRootDir(buildRoot)
66-
maybeProperties <- fileAlg.readFile(buildRootDir / "project" / "build.properties")
53+
maybeProperties <- fileAlg.readFile(buildRootDir / project / "build.properties")
6754
version = maybeProperties.flatMap(parser.parseBuildProperties)
6855
} yield version
6956

7057
override def getDependencies(buildRoot: BuildRoot): F[List[Scope.Dependencies]] =
58+
addStewardPluginTemporarily(buildRoot).surround {
59+
for {
60+
buildRootDir <- workspaceAlg.buildRootDir(buildRoot)
61+
commands = Nel.of(crossStewardDependencies, reloadPlugins, stewardDependencies)
62+
lines <- sbt(commands, buildRootDir)
63+
dependencies = parser.parseDependencies(lines)
64+
additionalDependencies <- getAdditionalDependencies(buildRoot)
65+
} yield additionalDependencies ::: dependencies
66+
}
67+
68+
private def addStewardPluginTemporarily(buildRoot: BuildRoot): Resource[F, Unit] =
7169
for {
72-
buildRootDir <- workspaceAlg.buildRootDir(buildRoot)
73-
commands = Nel.of(crossStewardDependencies, reloadPlugins, stewardDependencies)
74-
lines <- sbt(commands, buildRootDir)
75-
dependencies = parser.parseDependencies(lines)
76-
additionalDependencies <- getAdditionalDependencies(buildRoot)
77-
} yield additionalDependencies ::: dependencies
70+
buildRootDir <- Resource.eval(workspaceAlg.buildRootDir(buildRoot))
71+
plugin <- Resource.eval(stewardPlugin[F])
72+
_ <- fileAlg.createTemporarily(buildRootDir / project, plugin)
73+
_ <- fileAlg.createTemporarily(buildRootDir / project / project, plugin)
74+
} yield ()
7875

7976
override def runMigration(buildRoot: BuildRoot, migration: ScalafixMigration): F[Unit] =
8077
migration.targetOrDefault match {
@@ -83,31 +80,29 @@ final class SbtAlg[F[_]](config: Config)(implicit
8380
}
8481

8582
private def runSourcesMigration(buildRoot: BuildRoot, migration: ScalafixMigration): F[Unit] =
86-
sbtScalaFixPluginVersion.foreachF { pluginVersion =>
87-
addGlobalPluginTemporarily(scalaStewardScalafixSbt(pluginVersion)).surround {
88-
workspaceAlg.buildRootDir(buildRoot).flatMap { buildRootDir =>
89-
val withScalacOptions =
90-
migration.scalacOptions.fold(Resource.unit[F]) { opts =>
91-
val file = scalaStewardScalafixOptions(opts.toList)
92-
fileAlg.createTemporarily(buildRootDir / file.name, file.content)
93-
}
83+
OptionT(latestSbtScalafixVersion).foreachF { pluginVersion =>
84+
workspaceAlg.buildRootDir(buildRoot).flatMap { buildRootDir =>
85+
val plugin = scalaStewardSbtScalafix(pluginVersion)
86+
fileAlg.createTemporarily(buildRootDir / project, plugin).surround {
87+
val withScalacOptions = migration.scalacOptions.fold(Resource.unit[F]) { opts =>
88+
val options = scalaStewardScalafixOptions(opts.toList)
89+
fileAlg.createTemporarily(buildRootDir, options)
90+
}
9491
val scalafixCmds = migration.rewriteRules.map(rule => s"$scalafixAll $rule").toList
9592
withScalacOptions.surround(sbt(Nel(scalafixEnable, scalafixCmds), buildRootDir).void)
9693
}
9794
}
9895
}
9996

100-
private def sbtScalaFixPluginVersion: OptionT[F, String] =
101-
OptionT(
102-
versionsCache
103-
.getVersions(Scope(sbtScalaFixDependency, List(config.defaultResolver)), None)
104-
.map(_.lastOption.map(_.value))
105-
)
97+
private def latestSbtScalafixVersion: F[Option[Version]] =
98+
versionsCache
99+
.getVersions(Scope(sbtScalafixDependency, List(config.defaultResolver)), None)
100+
.map(_.lastOption)
106101

107102
private def runBuildMigration(buildRoot: BuildRoot, migration: ScalafixMigration): F[Unit] =
108103
for {
109104
buildRootDir <- workspaceAlg.buildRootDir(buildRoot)
110-
projectDir = buildRootDir / "project"
105+
projectDir = buildRootDir / project
111106
files0 <- (
112107
fileAlg.walk(buildRootDir, 1).filter(_.extension.contains(".sbt")) ++
113108
fileAlg.walk(projectDir, 3).filter(_.extension.exists(Set(".sbt", ".scala")))
@@ -117,9 +112,6 @@ final class SbtAlg[F[_]](config: Config)(implicit
117112
}
118113
} yield ()
119114

120-
private val sbtDir: F[File] =
121-
fileAlg.home.map(_ / ".sbt")
122-
123115
private def sbt(sbtCommands: Nel[String], repoDir: File): F[List[String]] =
124116
maybeIgnoreOptsFiles(repoDir).surround {
125117
val command =
@@ -133,7 +125,7 @@ final class SbtAlg[F[_]](config: Config)(implicit
133125
processAlg.execSandboxed(command, repoDir)
134126
}
135127

136-
private def maybeIgnoreOptsFiles[A](dir: File): Resource[F, Unit] =
128+
private def maybeIgnoreOptsFiles(dir: File): Resource[F, Unit] =
137129
if (config.ignoreOptsFiles) ignoreOptsFiles(dir) else Resource.unit[F]
138130

139131
private def ignoreOptsFiles(dir: File): Resource[F, Unit] =
@@ -142,4 +134,6 @@ final class SbtAlg[F[_]](config: Config)(implicit
142134
private def getAdditionalDependencies(buildRoot: BuildRoot): F[List[Scope.Dependencies]] =
143135
getSbtDependency(buildRoot)
144136
.map(_.map(dep => Scope(List(dep), List(config.defaultResolver))).toList)
137+
138+
private val project = "project"
145139
}

modules/core/src/main/scala/org/scalasteward/core/buildtool/sbt/package.scala

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -35,23 +35,24 @@ package object sbt {
3535
Option.when(version >= Version("1.0.0"))(Dependency(sbtGroupId, sbtArtifactId, version))
3636
}
3737

38-
val sbtScalaFixGroupId = GroupId("ch.epfl.scala")
39-
val sbtScalaFixArtifactId = ArtifactId("sbt-scalafix")
38+
val sbtScalafixGroupId: GroupId = GroupId("ch.epfl.scala")
4039

41-
val sbtScalaFixDependency: Dependency =
40+
val sbtScalafixArtifactId: ArtifactId = ArtifactId("sbt-scalafix")
41+
42+
val sbtScalafixDependency: Dependency =
4243
Dependency(
43-
sbtScalaFixGroupId,
44-
sbtScalaFixArtifactId,
44+
sbtScalafixGroupId,
45+
sbtScalafixArtifactId,
4546
Version(""),
4647
Some(SbtVersion("1.0")),
4748
Some(ScalaVersion("2.12"))
4849
)
4950

50-
def scalaStewardScalafixSbt(version: String): FileData =
51-
FileData(
52-
"scala-steward-scalafix.sbt",
53-
s"""addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % "$version")"""
54-
)
51+
def scalaStewardSbtScalafix(version: Version): FileData = {
52+
val content =
53+
s"""addSbtPlugin("${sbtScalafixGroupId.value}" % "${sbtScalafixArtifactId.name}" % "$version")"""
54+
FileData("scala-steward-sbt-scalafix.sbt", content)
55+
}
5556

5657
def scalaStewardScalafixOptions(scalacOptions: List[String]): FileData = {
5758
val args = scalacOptions.map(s => s""""$s"""").mkString(", ")
@@ -63,6 +64,6 @@ package object sbt {
6364
val name = "StewardPlugin.scala"
6465
fileAlg
6566
.readResource(s"${pkg.replace('.', '/')}/$name")
66-
.map(FileData(name, _))
67+
.map(FileData(s"scala-steward-$name", _))
6768
}
6869
}

modules/core/src/main/scala/org/scalasteward/core/edit/hooks/HookExecutor.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ import cats.syntax.all._
2222
import org.scalasteward.core.buildtool.sbt.{
2323
sbtArtifactId,
2424
sbtGroupId,
25-
sbtScalaFixArtifactId,
26-
sbtScalaFixGroupId
25+
sbtScalafixArtifactId,
26+
sbtScalafixGroupId
2727
}
2828
import org.scalasteward.core.data._
2929
import org.scalasteward.core.edit.EditAttempt
@@ -123,7 +123,7 @@ object HookExecutor {
123123

124124
// Modules that most likely require the workflow to be regenerated if updated.
125125
private val conditionalSbtGitHubWorkflowGenerateModules =
126-
(sbtGroupId, sbtArtifactId) :: (sbtScalaFixGroupId, sbtScalaFixArtifactId) :: scalaLangModules
126+
(sbtGroupId, sbtArtifactId) :: (sbtScalafixGroupId, sbtScalafixArtifactId) :: scalaLangModules
127127

128128
private def sbtGithubWorkflowGenerateHook(
129129
groupId: GroupId,

modules/core/src/main/scala/org/scalasteward/core/io/FileAlg.scala

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,6 @@ trait FileAlg[F[_]] {
3232

3333
def ensureExists(dir: File): F[File]
3434

35-
def home: F[File]
36-
3735
def isDirectory(file: File): F[Boolean]
3836

3937
def isRegularFile(file: File): F[Boolean]
@@ -58,6 +56,11 @@ trait FileAlg[F[_]] {
5856
Resource.make(create)(_ => delete)
5957
}
6058

59+
final def createTemporarily[E](dir: File, data: FileData)(implicit
60+
F: ApplicativeError[F, E]
61+
): Resource[F, Unit] =
62+
createTemporarily(dir / data.name, data.content)
63+
6164
final def editFile(file: File, edit: String => Option[String])(implicit
6265
F: MonadThrow[F]
6366
): F[Boolean] =
@@ -99,9 +102,6 @@ object FileAlg {
99102
dir
100103
}
101104

102-
override def home: F[File] =
103-
F.delay(File.home)
104-
105105
override def isDirectory(file: File): F[Boolean] =
106106
F.blocking(file.isDirectory(File.LinkOptions.noFollow))
107107

modules/core/src/test/scala/org/scalasteward/core/buildtool/BuildToolDispatcherTest.scala

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ class BuildToolDispatcherTest extends FunSuite {
3333
Cmd("test", "-f", s"$repoDir/pom.xml"),
3434
Cmd("test", "-f", s"$repoDir/build.sc"),
3535
Cmd("test", "-f", s"$repoDir/build.sbt"),
36+
Cmd("read", "classpath:org/scalasteward/sbt/plugin/StewardPlugin.scala"),
37+
Cmd("write", s"$repoDir/project/scala-steward-StewardPlugin.scala"),
38+
Cmd("write", s"$repoDir/project/project/scala-steward-StewardPlugin.scala"),
3639
Cmd(
3740
repoDir.toString,
3841
"firejail",
@@ -47,6 +50,8 @@ class BuildToolDispatcherTest extends FunSuite {
4750
s";$crossStewardDependencies;$reloadPlugins;$stewardDependencies"
4851
),
4952
Cmd("read", s"$repoDir/project/build.properties"),
53+
Cmd("rm", "-rf", s"$repoDir/project/project/scala-steward-StewardPlugin.scala"),
54+
Cmd("rm", "-rf", s"$repoDir/project/scala-steward-StewardPlugin.scala"),
5055
Cmd("read", s"$repoDir/$scalafmtConfName")
5156
)
5257
)

modules/core/src/test/scala/org/scalasteward/core/buildtool/sbt/SbtAlgTest.scala

Lines changed: 12 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package org.scalasteward.core.buildtool.sbt
22

3-
import cats.data.Kleisli
43
import cats.effect.unsafe.implicits.global
54
import munit.FunSuite
65
import org.scalasteward.core.buildtool.sbt.command._
@@ -9,30 +8,11 @@ import org.scalasteward.core.edit.scalafix.ScalafixMigration
98
import org.scalasteward.core.mock.MockConfig.{config, mockRoot}
109
import org.scalasteward.core.mock.MockContext.context.sbtAlg
1110
import org.scalasteward.core.mock.MockState
12-
import org.scalasteward.core.mock.MockState.TraceEntry.{Cmd, Log}
11+
import org.scalasteward.core.mock.MockState.TraceEntry.Cmd
1312
import org.scalasteward.core.util.Nel
1413
import org.scalasteward.core.vcs.data.{BuildRoot, Repo}
1514

1615
class SbtAlgTest extends FunSuite {
17-
test("addGlobalPlugins") {
18-
val obtained = sbtAlg.addGlobalPlugins
19-
.surround(Kleisli(_.update(_.exec(List("fa")))))
20-
.runS(MockState.empty)
21-
.unsafeRunSync()
22-
val expected = MockState.empty.copy(
23-
trace = Vector(
24-
Log("Add global sbt plugins"),
25-
Cmd("read", "classpath:org/scalasteward/sbt/plugin/StewardPlugin.scala"),
26-
Cmd("write", s"$mockRoot/.sbt/0.13/plugins/StewardPlugin.scala"),
27-
Cmd("write", s"$mockRoot/.sbt/1.0/plugins/StewardPlugin.scala"),
28-
Cmd("fa"),
29-
Cmd("rm", "-rf", s"$mockRoot/.sbt/1.0/plugins/StewardPlugin.scala"),
30-
Cmd("rm", "-rf", s"$mockRoot/.sbt/0.13/plugins/StewardPlugin.scala")
31-
)
32-
)
33-
assertEquals(obtained, expected)
34-
}
35-
3616
test("getDependencies") {
3717
val repo = Repo("typelevel", "cats")
3818
val buildRoot = BuildRoot(repo, ".")
@@ -42,6 +22,9 @@ class SbtAlgTest extends FunSuite {
4222
val state = sbtAlg.getDependencies(buildRoot).runS(initial).unsafeRunSync()
4323
val expected = initial.copy(
4424
trace = Vector(
25+
Cmd("read", "classpath:org/scalasteward/sbt/plugin/StewardPlugin.scala"),
26+
Cmd("write", s"$repoDir/project/scala-steward-StewardPlugin.scala"),
27+
Cmd("write", s"$repoDir/project/project/scala-steward-StewardPlugin.scala"),
4528
Cmd(
4629
repoDir.toString,
4730
"firejail",
@@ -55,7 +38,9 @@ class SbtAlgTest extends FunSuite {
5538
"-Dsbt.supershell=false",
5639
s";$crossStewardDependencies;$reloadPlugins;$stewardDependencies"
5740
),
58-
Cmd("read", s"$repoDir/project/build.properties")
41+
Cmd("read", s"$repoDir/project/build.properties"),
42+
Cmd("rm", "-rf", s"$repoDir/project/project/scala-steward-StewardPlugin.scala"),
43+
Cmd("rm", "-rf", s"$repoDir/project/scala-steward-StewardPlugin.scala")
5944
)
6045
)
6146
assertEquals(state, expected)
@@ -83,8 +68,7 @@ class SbtAlgTest extends FunSuite {
8368
"read",
8469
s"$mockRoot/workspace/store/versions/v2/https/repo1.maven.org/maven2/ch/epfl/scala/sbt-scalafix_2.12_1.0/versions.json"
8570
),
86-
Cmd("write", s"$mockRoot/.sbt/0.13/plugins/scala-steward-scalafix.sbt"),
87-
Cmd("write", s"$mockRoot/.sbt/1.0/plugins/scala-steward-scalafix.sbt"),
71+
Cmd("write", s"$repoDir/project/scala-steward-sbt-scalafix.sbt"),
8872
Cmd(
8973
repoDir.toString,
9074
"firejail",
@@ -98,8 +82,7 @@ class SbtAlgTest extends FunSuite {
9882
"-Dsbt.supershell=false",
9983
s";$scalafixEnable;$scalafixAll github:functional-streams-for-scala/fs2/v1?sha=v1.0.5"
10084
),
101-
Cmd("rm", "-rf", s"$mockRoot/.sbt/1.0/plugins/scala-steward-scalafix.sbt"),
102-
Cmd("rm", "-rf", s"$mockRoot/.sbt/0.13/plugins/scala-steward-scalafix.sbt")
85+
Cmd("rm", "-rf", s"$repoDir/project/scala-steward-sbt-scalafix.sbt")
10386
)
10487
)
10588
assertEquals(state, expected)
@@ -128,8 +111,7 @@ class SbtAlgTest extends FunSuite {
128111
"read",
129112
s"$mockRoot/workspace/store/versions/v2/https/repo1.maven.org/maven2/ch/epfl/scala/sbt-scalafix_2.12_1.0/versions.json"
130113
),
131-
Cmd("write", s"$mockRoot/.sbt/0.13/plugins/scala-steward-scalafix.sbt"),
132-
Cmd("write", s"$mockRoot/.sbt/1.0/plugins/scala-steward-scalafix.sbt"),
114+
Cmd("write", s"$repoDir/project/scala-steward-sbt-scalafix.sbt"),
133115
Cmd("write", s"$repoDir/scala-steward-scalafix-options.sbt"),
134116
Cmd(
135117
repoDir.toString,
@@ -145,14 +127,13 @@ class SbtAlgTest extends FunSuite {
145127
s";$scalafixEnable;$scalafixAll github:cb372/cats/Cats_v2_2_0?sha=235bd7c92e431ab1902db174cf4665b05e08f2f1"
146128
),
147129
Cmd("rm", "-rf", s"$repoDir/scala-steward-scalafix-options.sbt"),
148-
Cmd("rm", "-rf", s"$mockRoot/.sbt/1.0/plugins/scala-steward-scalafix.sbt"),
149-
Cmd("rm", "-rf", s"$mockRoot/.sbt/0.13/plugins/scala-steward-scalafix.sbt")
130+
Cmd("rm", "-rf", s"$repoDir/project/scala-steward-sbt-scalafix.sbt")
150131
)
151132
)
152133
assertEquals(state, expected)
153134
}
154135

155-
private val sbtScalafixVersionJson =
136+
private def sbtScalafixVersionJson =
156137
s"""|{
157138
| "updatedAt" : 9999999999999,
158139
| "versions" : [

0 commit comments

Comments
 (0)