Repository: scala-steward-org/scala-steward (scala)

Issue:
Should not hard-code SBT home
Currently, scala-steward silently assumes that SBT's home directory is `~/.sbt`.

There are various launcher options for SBT (configured system wide in `/etc/sbtops` or via `SBT_OPTS`) which relocate that directory.

I for one, would like to use the `--no-share` option which sets `-Dsbt.global.base=project/.sbtboot` `-Dsbt.boot.directory=project/.boot` `-Dsbt.ivy.home=project/.ivy`.

It would be good if scala-steward would honor those settings too, or at least document that you cannot relocate your SBT folder.

Pull request description:
`StewardPlugin.scala` is the sbt plugin that outputs all relevant information from a build for consumption by Scala Steward. That plugin has been installed so far globally at the start of Scala Steward into sbt's home directory. With this PR, that plugin is now installed into the local `project/` directories as long as it is needed to run `sbt stewardDependencies`.

This change is motivated by #2847 - i.e. only sbt >= 1.3.0 can currently load our sbt plugin. With this change we would be able to use different plugins dependending on a repo's sbt version.

closes: #1624

Patch:
diff --git a/modules/core/src/main/scala/org/scalasteward/core/application/StewardAlg.scala b/modules/core/src/main/scala/org/scalasteward/core/application/StewardAlg.scala
index 94944ed7f1..2fc2e50e47 100644
--- a/modules/core/src/main/scala/org/scalasteward/core/application/StewardAlg.scala
+++ b/modules/core/src/main/scala/org/scalasteward/core/application/StewardAlg.scala
@@ -20,7 +20,6 @@ import better.files.File
 import cats.effect.{ExitCode, Sync}
 import cats.syntax.all._
 import fs2.Stream
-import org.scalasteward.core.buildtool.sbt.SbtAlg
 import org.scalasteward.core.git.GitAlg
 import org.scalasteward.core.io.{FileAlg, WorkspaceAlg}
 import org.scalasteward.core.nurture.NurtureAlg
@@ -44,7 +43,6 @@ final class StewardAlg[F[_]](config: Config)(implicit
     nurtureAlg: NurtureAlg[F],
     pruningAlg: PruningAlg[F],
     repoCacheAlg: RepoCacheAlg[F],
-    sbtAlg: SbtAlg[F],
     selfCheckAlg: SelfCheckAlg[F],
     workspaceAlg: WorkspaceAlg[F],
     F: Sync[F]
@@ -95,7 +93,7 @@ final class StewardAlg[F[_]](config: Config)(implicit
       for {
         _ <- selfCheckAlg.checkAll
         _ <- workspaceAlg.cleanWorkspace
-        exitCode <- sbtAlg.addGlobalPlugins.surround {
+        exitCode <-
           (config.githubApp.map(getGitHubAppRepos).getOrElse(Stream.empty) ++
             readRepos(config.reposFile))
             .evalMap(steward)
@@ -109,7 +107,6 @@ final class StewardAlg[F[_]](config: Config)(implicit
                   s"""The format is "- $$owner/$$repo" or "- $$owner/$$repo:$$branch"."""
                 logger.warn(msg).as(ExitCode.Success)
             }
-        }
       } yield exitCode
     }
 }
diff --git a/modules/core/src/main/scala/org/scalasteward/core/buildtool/sbt/SbtAlg.scala b/modules/core/src/main/scala/org/scalasteward/core/buildtool/sbt/SbtAlg.scala
index c7e5ddce04..244d371c2b 100644
--- a/modules/core/src/main/scala/org/scalasteward/core/buildtool/sbt/SbtAlg.scala
+++ b/modules/core/src/main/scala/org/scalasteward/core/buildtool/sbt/SbtAlg.scala
@@ -25,16 +25,14 @@ import org.scalasteward.core.buildtool.BuildToolAlg
 import org.scalasteward.core.buildtool.sbt.command._
 import org.scalasteward.core.buildtool.sbt.data.SbtVersion
 import org.scalasteward.core.coursier.VersionsCache
-import org.scalasteward.core.data.{Dependency, Scope}
+import org.scalasteward.core.data.{Dependency, Scope, Version}
 import org.scalasteward.core.edit.scalafix.{ScalafixCli, ScalafixMigration}
-import org.scalasteward.core.io.{FileAlg, FileData, ProcessAlg, WorkspaceAlg}
+import org.scalasteward.core.io.{FileAlg, ProcessAlg, WorkspaceAlg}
 import org.scalasteward.core.util.Nel
 import org.scalasteward.core.vcs.data.BuildRoot
-import org.typelevel.log4cats.Logger
 
 final class SbtAlg[F[_]](config: Config)(implicit
     fileAlg: FileAlg[F],
-    logger: Logger[F],
     processAlg: ProcessAlg[F],
     scalafixCli: ScalafixCli[F],
     workspaceAlg: WorkspaceAlg[F],
@@ -44,17 +42,6 @@ final class SbtAlg[F[_]](config: Config)(implicit
   private def getSbtDependency(buildRoot: BuildRoot): F[Option[Dependency]] =
     OptionT(getSbtVersion(buildRoot)).subflatMap(sbtDependency).value
 
-  private def addGlobalPluginTemporarily(plugin: FileData): Resource[F, Unit] =
-    Resource.eval(sbtDir).flatMap { dir =>
-      List("0.13", "1.0").traverse_ { version =>
-        fileAlg.createTemporarily(dir / version / "plugins" / plugin.name, plugin.content)
-      }
-    }
-
-  def addGlobalPlugins: Resource[F, Unit] =
-    Resource.eval(logger.info("Add global sbt plugins")) >>
-      Resource.eval(stewardPlugin).flatMap(addGlobalPluginTemporarily)
-
   override def containsBuild(buildRoot: BuildRoot): F[Boolean] =
     workspaceAlg
       .buildRootDir(buildRoot)
@@ -63,18 +50,28 @@ final class SbtAlg[F[_]](config: Config)(implicit
   private def getSbtVersion(buildRoot: BuildRoot): F[Option[SbtVersion]] =
     for {
       buildRootDir <- workspaceAlg.buildRootDir(buildRoot)
-      maybeProperties <- fileAlg.readFile(buildRootDir / "project" / "build.properties")
+      maybeProperties <- fileAlg.readFile(buildRootDir / project / "build.properties")
       version = maybeProperties.flatMap(parser.parseBuildProperties)
     } yield version
 
   override def getDependencies(buildRoot: BuildRoot): F[List[Scope.Dependencies]] =
+    addStewardPluginTemporarily(buildRoot).surround {
+      for {
+        buildRootDir <- workspaceAlg.buildRootDir(buildRoot)
+        commands = Nel.of(crossStewardDependencies, reloadPlugins, stewardDependencies)
+        lines <- sbt(commands, buildRootDir)
+        dependencies = parser.parseDependencies(lines)
+        additionalDependencies <- getAdditionalDependencies(buildRoot)
+      } yield additionalDependencies ::: dependencies
+    }
+
+  private def addStewardPluginTemporarily(buildRoot: BuildRoot): Resource[F, Unit] =
     for {
-      buildRootDir <- workspaceAlg.buildRootDir(buildRoot)
-      commands = Nel.of(crossStewardDependencies, reloadPlugins, stewardDependencies)
-      lines <- sbt(commands, buildRootDir)
-      dependencies = parser.parseDependencies(lines)
-      additionalDependencies <- getAdditionalDependencies(buildRoot)
-    } yield additionalDependencies ::: dependencies
+      buildRootDir <- Resource.eval(workspaceAlg.buildRootDir(buildRoot))
+      plugin <- Resource.eval(stewardPlugin[F])
+      _ <- fileAlg.createTemporarily(buildRootDir / project, plugin)
+      _ <- fileAlg.createTemporarily(buildRootDir / project / project, plugin)
+    } yield ()
 
   override def runMigration(buildRoot: BuildRoot, migration: ScalafixMigration): F[Unit] =
     migration.targetOrDefault match {
@@ -83,31 +80,29 @@ final class SbtAlg[F[_]](config: Config)(implicit
     }
 
   private def runSourcesMigration(buildRoot: BuildRoot, migration: ScalafixMigration): F[Unit] =
-    sbtScalaFixPluginVersion.foreachF { pluginVersion =>
-      addGlobalPluginTemporarily(scalaStewardScalafixSbt(pluginVersion)).surround {
-        workspaceAlg.buildRootDir(buildRoot).flatMap { buildRootDir =>
-          val withScalacOptions =
-            migration.scalacOptions.fold(Resource.unit[F]) { opts =>
-              val file = scalaStewardScalafixOptions(opts.toList)
-              fileAlg.createTemporarily(buildRootDir / file.name, file.content)
-            }
+    OptionT(latestSbtScalafixVersion).foreachF { pluginVersion =>
+      workspaceAlg.buildRootDir(buildRoot).flatMap { buildRootDir =>
+        val plugin = scalaStewardSbtScalafix(pluginVersion)
+        fileAlg.createTemporarily(buildRootDir / project, plugin).surround {
+          val withScalacOptions = migration.scalacOptions.fold(Resource.unit[F]) { opts =>
+            val options = scalaStewardScalafixOptions(opts.toList)
+            fileAlg.createTemporarily(buildRootDir, options)
+          }
           val scalafixCmds = migration.rewriteRules.map(rule => s"$scalafixAll $rule").toList
           withScalacOptions.surround(sbt(Nel(scalafixEnable, scalafixCmds), buildRootDir).void)
         }
       }
     }
 
-  private def sbtScalaFixPluginVersion: OptionT[F, String] =
-    OptionT(
-      versionsCache
-        .getVersions(Scope(sbtScalaFixDependency, List(config.defaultResolver)), None)
-        .map(_.lastOption.map(_.value))
-    )
+  private def latestSbtScalafixVersion: F[Option[Version]] =
+    versionsCache
+      .getVersions(Scope(sbtScalafixDependency, List(config.defaultResolver)), None)
+      .map(_.lastOption)
 
   private def runBuildMigration(buildRoot: BuildRoot, migration: ScalafixMigration): F[Unit] =
     for {
       buildRootDir <- workspaceAlg.buildRootDir(buildRoot)
-      projectDir = buildRootDir / "project"
+      projectDir = buildRootDir / project
       files0 <- (
         fileAlg.walk(buildRootDir, 1).filter(_.extension.contains(".sbt")) ++
           fileAlg.walk(projectDir, 3).filter(_.extension.exists(Set(".sbt", ".scala")))
@@ -117,9 +112,6 @@ final class SbtAlg[F[_]](config: Config)(implicit
       }
     } yield ()
 
-  private val sbtDir: F[File] =
-    fileAlg.home.map(_ / ".sbt")
-
   private def sbt(sbtCommands: Nel[String], repoDir: File): F[List[String]] =
     maybeIgnoreOptsFiles(repoDir).surround {
       val command =
@@ -133,7 +125,7 @@ final class SbtAlg[F[_]](config: Config)(implicit
       processAlg.execSandboxed(command, repoDir)
     }
 
-  private def maybeIgnoreOptsFiles[A](dir: File): Resource[F, Unit] =
+  private def maybeIgnoreOptsFiles(dir: File): Resource[F, Unit] =
     if (config.ignoreOptsFiles) ignoreOptsFiles(dir) else Resource.unit[F]
 
   private def ignoreOptsFiles(dir: File): Resource[F, Unit] =
@@ -142,4 +134,6 @@ final class SbtAlg[F[_]](config: Config)(implicit
   private def getAdditionalDependencies(buildRoot: BuildRoot): F[List[Scope.Dependencies]] =
     getSbtDependency(buildRoot)
       .map(_.map(dep => Scope(List(dep), List(config.defaultResolver))).toList)
+
+  private val project = "project"
 }
diff --git a/modules/core/src/main/scala/org/scalasteward/core/buildtool/sbt/package.scala b/modules/core/src/main/scala/org/scalasteward/core/buildtool/sbt/package.scala
index 2aa3a9dd5b..7a15c3d5ba 100644
--- a/modules/core/src/main/scala/org/scalasteward/core/buildtool/sbt/package.scala
+++ b/modules/core/src/main/scala/org/scalasteward/core/buildtool/sbt/package.scala
@@ -35,23 +35,24 @@ package object sbt {
     Option.when(version >= Version("1.0.0"))(Dependency(sbtGroupId, sbtArtifactId, version))
   }
 
-  val sbtScalaFixGroupId = GroupId("ch.epfl.scala")
-  val sbtScalaFixArtifactId = ArtifactId("sbt-scalafix")
+  val sbtScalafixGroupId: GroupId = GroupId("ch.epfl.scala")
 
-  val sbtScalaFixDependency: Dependency =
+  val sbtScalafixArtifactId: ArtifactId = ArtifactId("sbt-scalafix")
+
+  val sbtScalafixDependency: Dependency =
     Dependency(
-      sbtScalaFixGroupId,
-      sbtScalaFixArtifactId,
+      sbtScalafixGroupId,
+      sbtScalafixArtifactId,
       Version(""),
       Some(SbtVersion("1.0")),
       Some(ScalaVersion("2.12"))
     )
 
-  def scalaStewardScalafixSbt(version: String): FileData =
-    FileData(
-      "scala-steward-scalafix.sbt",
-      s"""addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % "$version")"""
-    )
+  def scalaStewardSbtScalafix(version: Version): FileData = {
+    val content =
+      s"""addSbtPlugin("${sbtScalafixGroupId.value}" % "${sbtScalafixArtifactId.name}" % "$version")"""
+    FileData("scala-steward-sbt-scalafix.sbt", content)
+  }
 
   def scalaStewardScalafixOptions(scalacOptions: List[String]): FileData = {
     val args = scalacOptions.map(s => s""""$s"""").mkString(", ")
@@ -63,6 +64,6 @@ package object sbt {
     val name = "StewardPlugin.scala"
     fileAlg
       .readResource(s"${pkg.replace('.', '/')}/$name")
-      .map(FileData(name, _))
+      .map(FileData(s"scala-steward-$name", _))
   }
 }
diff --git a/modules/core/src/main/scala/org/scalasteward/core/edit/hooks/HookExecutor.scala b/modules/core/src/main/scala/org/scalasteward/core/edit/hooks/HookExecutor.scala
index 01de4fae3d..4396def2eb 100644
--- a/modules/core/src/main/scala/org/scalasteward/core/edit/hooks/HookExecutor.scala
+++ b/modules/core/src/main/scala/org/scalasteward/core/edit/hooks/HookExecutor.scala
@@ -22,8 +22,8 @@ import cats.syntax.all._
 import org.scalasteward.core.buildtool.sbt.{
   sbtArtifactId,
   sbtGroupId,
-  sbtScalaFixArtifactId,
-  sbtScalaFixGroupId
+  sbtScalafixArtifactId,
+  sbtScalafixGroupId
 }
 import org.scalasteward.core.data._
 import org.scalasteward.core.edit.EditAttempt
@@ -123,7 +123,7 @@ object HookExecutor {
 
   // Modules that most likely require the workflow to be regenerated if updated.
   private val conditionalSbtGitHubWorkflowGenerateModules =
-    (sbtGroupId, sbtArtifactId) :: (sbtScalaFixGroupId, sbtScalaFixArtifactId) :: scalaLangModules
+    (sbtGroupId, sbtArtifactId) :: (sbtScalafixGroupId, sbtScalafixArtifactId) :: scalaLangModules
 
   private def sbtGithubWorkflowGenerateHook(
       groupId: GroupId,
diff --git a/modules/core/src/main/scala/org/scalasteward/core/io/FileAlg.scala b/modules/core/src/main/scala/org/scalasteward/core/io/FileAlg.scala
index ad7975e327..8d228f1b7f 100644
--- a/modules/core/src/main/scala/org/scalasteward/core/io/FileAlg.scala
+++ b/modules/core/src/main/scala/org/scalasteward/core/io/FileAlg.scala
@@ -32,8 +32,6 @@ trait FileAlg[F[_]] {
 
   def ensureExists(dir: File): F[File]
 
-  def home: F[File]
-
   def isDirectory(file: File): F[Boolean]
 
   def isRegularFile(file: File): F[Boolean]
@@ -58,6 +56,11 @@ trait FileAlg[F[_]] {
     Resource.make(create)(_ => delete)
   }
 
+  final def createTemporarily[E](dir: File, data: FileData)(implicit
+      F: ApplicativeError[F, E]
+  ): Resource[F, Unit] =
+    createTemporarily(dir / data.name, data.content)
+
   final def editFile(file: File, edit: String => Option[String])(implicit
       F: MonadThrow[F]
   ): F[Boolean] =
@@ -99,9 +102,6 @@ object FileAlg {
           dir
         }
 
-      override def home: F[File] =
-        F.delay(File.home)
-
       override def isDirectory(file: File): F[Boolean] =
         F.blocking(file.isDirectory(File.LinkOptions.noFollow))
 


Test patch:
diff --git a/modules/core/src/test/scala/org/scalasteward/core/buildtool/BuildToolDispatcherTest.scala b/modules/core/src/test/scala/org/scalasteward/core/buildtool/BuildToolDispatcherTest.scala
index d3b057b78d..fc5c42dd06 100644
--- a/modules/core/src/test/scala/org/scalasteward/core/buildtool/BuildToolDispatcherTest.scala
+++ b/modules/core/src/test/scala/org/scalasteward/core/buildtool/BuildToolDispatcherTest.scala
@@ -33,6 +33,9 @@ class BuildToolDispatcherTest extends FunSuite {
         Cmd("test", "-f", s"$repoDir/pom.xml"),
         Cmd("test", "-f", s"$repoDir/build.sc"),
         Cmd("test", "-f", s"$repoDir/build.sbt"),
+        Cmd("read", "classpath:org/scalasteward/sbt/plugin/StewardPlugin.scala"),
+        Cmd("write", s"$repoDir/project/scala-steward-StewardPlugin.scala"),
+        Cmd("write", s"$repoDir/project/project/scala-steward-StewardPlugin.scala"),
         Cmd(
           repoDir.toString,
           "firejail",
@@ -47,6 +50,8 @@ class BuildToolDispatcherTest extends FunSuite {
           s";$crossStewardDependencies;$reloadPlugins;$stewardDependencies"
         ),
         Cmd("read", s"$repoDir/project/build.properties"),
+        Cmd("rm", "-rf", s"$repoDir/project/project/scala-steward-StewardPlugin.scala"),
+        Cmd("rm", "-rf", s"$repoDir/project/scala-steward-StewardPlugin.scala"),
         Cmd("read", s"$repoDir/$scalafmtConfName")
       )
     )
diff --git a/modules/core/src/test/scala/org/scalasteward/core/buildtool/sbt/SbtAlgTest.scala b/modules/core/src/test/scala/org/scalasteward/core/buildtool/sbt/SbtAlgTest.scala
index da6d6f1b03..b808af72aa 100644
--- a/modules/core/src/test/scala/org/scalasteward/core/buildtool/sbt/SbtAlgTest.scala
+++ b/modules/core/src/test/scala/org/scalasteward/core/buildtool/sbt/SbtAlgTest.scala
@@ -1,6 +1,5 @@
 package org.scalasteward.core.buildtool.sbt
 
-import cats.data.Kleisli
 import cats.effect.unsafe.implicits.global
 import munit.FunSuite
 import org.scalasteward.core.buildtool.sbt.command._
@@ -9,30 +8,11 @@ import org.scalasteward.core.edit.scalafix.ScalafixMigration
 import org.scalasteward.core.mock.MockConfig.{config, mockRoot}
 import org.scalasteward.core.mock.MockContext.context.sbtAlg
 import org.scalasteward.core.mock.MockState
-import org.scalasteward.core.mock.MockState.TraceEntry.{Cmd, Log}
+import org.scalasteward.core.mock.MockState.TraceEntry.Cmd
 import org.scalasteward.core.util.Nel
 import org.scalasteward.core.vcs.data.{BuildRoot, Repo}
 
 class SbtAlgTest extends FunSuite {
-  test("addGlobalPlugins") {
-    val obtained = sbtAlg.addGlobalPlugins
-      .surround(Kleisli(_.update(_.exec(List("fa")))))
-      .runS(MockState.empty)
-      .unsafeRunSync()
-    val expected = MockState.empty.copy(
-      trace = Vector(
-        Log("Add global sbt plugins"),
-        Cmd("read", "classpath:org/scalasteward/sbt/plugin/StewardPlugin.scala"),
-        Cmd("write", s"$mockRoot/.sbt/0.13/plugins/StewardPlugin.scala"),
-        Cmd("write", s"$mockRoot/.sbt/1.0/plugins/StewardPlugin.scala"),
-        Cmd("fa"),
-        Cmd("rm", "-rf", s"$mockRoot/.sbt/1.0/plugins/StewardPlugin.scala"),
-        Cmd("rm", "-rf", s"$mockRoot/.sbt/0.13/plugins/StewardPlugin.scala")
-      )
-    )
-    assertEquals(obtained, expected)
-  }
-
   test("getDependencies") {
     val repo = Repo("typelevel", "cats")
     val buildRoot = BuildRoot(repo, ".")
@@ -42,6 +22,9 @@ class SbtAlgTest extends FunSuite {
     val state = sbtAlg.getDependencies(buildRoot).runS(initial).unsafeRunSync()
     val expected = initial.copy(
       trace = Vector(
+        Cmd("read", "classpath:org/scalasteward/sbt/plugin/StewardPlugin.scala"),
+        Cmd("write", s"$repoDir/project/scala-steward-StewardPlugin.scala"),
+        Cmd("write", s"$repoDir/project/project/scala-steward-StewardPlugin.scala"),
         Cmd(
           repoDir.toString,
           "firejail",
@@ -55,7 +38,9 @@ class SbtAlgTest extends FunSuite {
           "-Dsbt.supershell=false",
           s";$crossStewardDependencies;$reloadPlugins;$stewardDependencies"
         ),
-        Cmd("read", s"$repoDir/project/build.properties")
+        Cmd("read", s"$repoDir/project/build.properties"),
+        Cmd("rm", "-rf", s"$repoDir/project/project/scala-steward-StewardPlugin.scala"),
+        Cmd("rm", "-rf", s"$repoDir/project/scala-steward-StewardPlugin.scala")
       )
     )
     assertEquals(state, expected)
@@ -83,8 +68,7 @@ class SbtAlgTest extends FunSuite {
           "read",
           s"$mockRoot/workspace/store/versions/v2/https/repo1.maven.org/maven2/ch/epfl/scala/sbt-scalafix_2.12_1.0/versions.json"
         ),
-        Cmd("write", s"$mockRoot/.sbt/0.13/plugins/scala-steward-scalafix.sbt"),
-        Cmd("write", s"$mockRoot/.sbt/1.0/plugins/scala-steward-scalafix.sbt"),
+        Cmd("write", s"$repoDir/project/scala-steward-sbt-scalafix.sbt"),
         Cmd(
           repoDir.toString,
           "firejail",
@@ -98,8 +82,7 @@ class SbtAlgTest extends FunSuite {
           "-Dsbt.supershell=false",
           s";$scalafixEnable;$scalafixAll github:functional-streams-for-scala/fs2/v1?sha=v1.0.5"
         ),
-        Cmd("rm", "-rf", s"$mockRoot/.sbt/1.0/plugins/scala-steward-scalafix.sbt"),
-        Cmd("rm", "-rf", s"$mockRoot/.sbt/0.13/plugins/scala-steward-scalafix.sbt")
+        Cmd("rm", "-rf", s"$repoDir/project/scala-steward-sbt-scalafix.sbt")
       )
     )
     assertEquals(state, expected)
@@ -128,8 +111,7 @@ class SbtAlgTest extends FunSuite {
           "read",
           s"$mockRoot/workspace/store/versions/v2/https/repo1.maven.org/maven2/ch/epfl/scala/sbt-scalafix_2.12_1.0/versions.json"
         ),
-        Cmd("write", s"$mockRoot/.sbt/0.13/plugins/scala-steward-scalafix.sbt"),
-        Cmd("write", s"$mockRoot/.sbt/1.0/plugins/scala-steward-scalafix.sbt"),
+        Cmd("write", s"$repoDir/project/scala-steward-sbt-scalafix.sbt"),
         Cmd("write", s"$repoDir/scala-steward-scalafix-options.sbt"),
         Cmd(
           repoDir.toString,
@@ -145,14 +127,13 @@ class SbtAlgTest extends FunSuite {
           s";$scalafixEnable;$scalafixAll github:cb372/cats/Cats_v2_2_0?sha=235bd7c92e431ab1902db174cf4665b05e08f2f1"
         ),
         Cmd("rm", "-rf", s"$repoDir/scala-steward-scalafix-options.sbt"),
-        Cmd("rm", "-rf", s"$mockRoot/.sbt/1.0/plugins/scala-steward-scalafix.sbt"),
-        Cmd("rm", "-rf", s"$mockRoot/.sbt/0.13/plugins/scala-steward-scalafix.sbt")
+        Cmd("rm", "-rf", s"$repoDir/project/scala-steward-sbt-scalafix.sbt")
       )
     )
     assertEquals(state, expected)
   }
 
-  private val sbtScalafixVersionJson =
+  private def sbtScalafixVersionJson =
     s"""|{
         |  "updatedAt" : 9999999999999,
         |  "versions" : [
diff --git a/modules/core/src/test/scala/org/scalasteward/core/io/FileAlgTest.scala b/modules/core/src/test/scala/org/scalasteward/core/io/FileAlgTest.scala
index 2a834fb1d9..cd535539d3 100644
--- a/modules/core/src/test/scala/org/scalasteward/core/io/FileAlgTest.scala
+++ b/modules/core/src/test/scala/org/scalasteward/core/io/FileAlgTest.scala
@@ -51,18 +51,18 @@ class FileAlgTest extends FunSuite {
   }
 
   test("removeTemporarily: nonexistent file") {
-    val file = mockRoot / "does-not-exists.txt"
+    val file = mockRoot / "does-not-exist.txt"
     assertEquals(ioFileAlg.removeTemporarily(file).surround(IO.pure(42)).unsafeRunSync(), 42)
   }
 
   test("editFile: nonexistent file") {
-    val (state, edited) = (for {
-      home <- fileAlg.home
-      edited <- fileAlg.editFile(home / "does-not-exists.txt", Some.apply)
-    } yield edited).runSA(MockState.empty).unsafeRunSync()
+    val (state, edited) = fileAlg
+      .editFile(mockRoot / "does-not-exist.txt", Some.apply)
+      .runSA(MockState.empty)
+      .unsafeRunSync()
 
     val expected =
-      MockState.empty.copy(trace = Vector(Cmd("read", s"$mockRoot/does-not-exists.txt")))
+      MockState.empty.copy(trace = Vector(Cmd("read", s"$mockRoot/does-not-exist.txt")))
     assertEquals(state, expected)
     assert(!edited)
   }
diff --git a/modules/core/src/test/scala/org/scalasteward/core/io/MockFileAlg.scala b/modules/core/src/test/scala/org/scalasteward/core/io/MockFileAlg.scala
index f456755076..091a6cc6f5 100644
--- a/modules/core/src/test/scala/org/scalasteward/core/io/MockFileAlg.scala
+++ b/modules/core/src/test/scala/org/scalasteward/core/io/MockFileAlg.scala
@@ -15,9 +15,6 @@ class MockFileAlg extends FileAlg[MockEff] {
   override def ensureExists(dir: File): MockEff[File] =
     Kleisli(_.update(_.exec(List("mkdir", "-p", dir.pathAsString))) >> ioFileAlg.ensureExists(dir))
 
-  override def home: MockEff[File] =
-    Kleisli.pure(MockConfig.mockRoot)
-
   override def isDirectory(file: File): MockEff[Boolean] =
     Kleisli(_.update(_.exec(List("test", "-d", file.pathAsString))) >> ioFileAlg.isDirectory(file))