Repository: scala-steward-org/scala-steward
Pull request #2995 (2023-02-28 23:21:25)

Check up to 5 nested project folders
Some projects set up plugins in `project/project/plugins.sbt` and even in `project/project/project/plugins.sbt` (I worked on such a private project, so I can't share details, but such things do exists :wink:)

For example, Play and the sbt-web-build-base project put [sbt-buildinfo](https://github.com/sbt/sbt-buildinfo) in their `project/project/plugins.sbt` files:
* https://github.com/playframework/playframework/blob/main/project/project/buildinfo.sbt
* https://github.com/sbt/sbt-web-build-base/blob/master/project/project/buildinfo.sbt

However, as you can see, even though scala-steward is enabled and visiting those repos, that plugin never gets updated ([latest release is 0.11.0](https://github.com/sbt/sbt-buildinfo/releases), also see [maven central](https://repo1.maven.org/maven2/com/eed3si9n/sbt-buildinfo_2.12_1.0/0.11.0/))

Making scala-steward check and update those dependencies is actually pretty easy and straight forward:
We just need to set up the special `scala-steward-StewardPlugin_<version>.scala` plugin in the corresponding `project/project/project/project/` and `project/project/project/` folders so they are available as plugins for the parent "build" and then just enter those sub "build" projects via `reloadPlugins` again and also run `stewardDependencies` which also logs the dependencies of those projects.
Nothing special, just a couple of more lines logged and parsed by scala steward.
I also think the test that I adjusted in this pull request explains everything.

To make sure everything works 100% I set up following test repo:
 * https://github.com/mkurz/three-level-sbt-plugins-project

As you can see it has three levels of `project` folders including `plugins.sbt`:
* https://github.com/mkurz/three-level-sbt-plugins-project/tree/main/project/project/project
* https://github.com/mkurz/three-level-sbt-plugins-project/tree/main/project/project
* https://github.com/mkurz/three-level-sbt-plugins-project/tree/main/project

So I added outdated plugins to each `plugins.sbt` and the `build.sbt` and ran scala steward with this pull request applied [locally](https://github.com/scala-steward-org/scala-steward/blob/main/docs/running.md#running-scala-steward) and voilà, scala steward opened all expected pull requests:
* https://github.com/mkurz/three-level-sbt-plugins-project/pull/3/files
* https://github.com/mkurz/three-level-sbt-plugins-project/pull/4/files
* https://github.com/mkurz/three-level-sbt-plugins-project/pull/1/files
* https://github.com/mkurz/three-level-sbt-plugins-project/pull/2/files

BTW:
If you want to test out what the output of the sbt command ran by sbt looks like, you can check out the [`steward-plugin-file` branch](https://github.com/mkurz/three-level-sbt-plugins-project/tree/steward-plugin-file) of my test repo and ran the sbt command I show in the README. It is [exactly what scala steward runs](https://github.com/scala-steward-org/scala-steward/blob/f8bc50b768b371be40ba07799333ad631e881c55/modules/core/src/main/scala/org/scalasteward/core/buildtool/sbt/SbtAlg.scala#L139-L143) to [figure out the versions](https://github.com/scala-steward-org/scala-steward/blob/f8bc50b768b371be40ba07799333ad631e881c55/modules/core/src/main/scala/org/scalasteward/core/buildtool/sbt/SbtAlg.scala#L59-L60). (For this to `stewardDependencies` command to work I [manually added](https://github.com/mkurz/three-level-sbt-plugins-project/commit/3f1d38431c81e60622b064cfc609377e0f543d03) the `StewardPlugin_1_3_11.scala` files myself, see the README again).

codecov[bot]: # [Codecov](https://codecov.io/gh/scala-steward-org/scala-steward/pull/2995?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=scala-steward-org) Report
Patch coverage: **`100.00`**% and project coverage change: **`+0.02`** :tada:
> Comparison is base [(`f8bc50b`)](https://codecov.io/gh/scala-steward-org/scala-steward/commit/f8bc50b768b371be40ba07799333ad631e881c55?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=scala-steward-org) 90.88% compared to head [(`9ab8af3`)](https://codecov.io/gh/scala-steward-org/scala-steward/pull/2995?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=scala-steward-org) 90.91%.

<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##             main    #2995      +/-   ##
==========================================
+ Coverage   90.88%   90.91%   +0.02%     
==========================================
  Files         160      160              
  Lines        3314     3323       +9     
  Branches      306      313       +7     
==========================================
+ Hits         3012     3021       +9     
  Misses        302      302              
```


| [Impacted Files](https://codecov.io/gh/scala-steward-org/scala-steward/pull/2995?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=scala-steward-org) | Coverage Δ | |
|---|---|---|
| [...a/org/scalasteward/core/buildtool/sbt/SbtAlg.scala](https://codecov.io/gh/scala-steward-org/scala-steward/pull/2995?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=scala-steward-org#diff-bW9kdWxlcy9jb3JlL3NyYy9tYWluL3NjYWxhL29yZy9zY2FsYXN0ZXdhcmQvY29yZS9idWlsZHRvb2wvc2J0L1NidEFsZy5zY2FsYQ==) | `98.52% <100.00%> (+0.22%)` | :arrow_up: |

Help us with your feedback. Take ten seconds to tell us [how you rate us](https://about.codecov.io/nps?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=scala-steward-org). Have a feature suggestion? [Share it here.](https://app.codecov.io/gh/feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=scala-steward-org)

</details>

[:umbrella: View full report at Codecov](https://codecov.io/gh/scala-steward-org/scala-steward/pull/2995?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=scala-steward-org).   
:loudspeaker: Do you have feedback about the report comment? [Let us know in this issue](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=scala-steward-org).

mkurz: Would be nice if this PR makes it into v0.22.0 :wink: 
mkurz: Hey! I am pretty sure this pull request is good to go, reviews would be highly appreciated. Thanks!
fthomas: Thanks for the PR, @mkurz! I'm fine with updating dependencies in meta-meta-builds and even meta-meta-meta-builds but I think it would be better to check how many nested `project` directories there are before calling `reload plugins; stewardDependencies` thrice. My concern is that calling `reload plugins` can take a few seconds and we're slowing down Scala Steward unnecessarily for the majority of sbt projects.

I would check how many (nested) `project` directories there are and then only adding the `StewardPlugin_*.scala` to them if they exist. We would then only need to call `reload plugins; stewardDependencies` as much as needed. 
mkurz: I get it. Will update when I find time, thanks!

Patch:
diff --git a/build.sbt b/build.sbt
index 879dc49b..b2e63eb1 100644
--- a/build.sbt
+++ b/build.sbt
@@ -121,7 +121,6 @@ lazy val core = myCrossProject("core")
       Dependencies.decline,
       Dependencies.fs2Core,
       Dependencies.fs2Io,
-      Dependencies.gitignore,
       Dependencies.http4sCirce,
       Dependencies.http4sClient,
       Dependencies.http4sCore,
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 c36e25b7..883d8316 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
@@ -51,12 +51,24 @@ final class SbtAlg[F[_]](config: Config)(implicit
       version = maybeProperties.flatMap(parser.parseBuildProperties)
     } yield version
 
+  private def metaBuildsCount(buildRootDir: File): F[Int] =
+    fs2.Stream
+      .iterate(buildRootDir / project)(_ / project)
+      .take(5L) // Use an upper bound for the meta-builds count to prevent DoS attacks.
+      .evalMap(fileAlg.isDirectory)
+      .takeWhile(identity)
+      .compile
+      .count
+      .map(_.toInt)
+
   override def getDependencies(buildRoot: BuildRoot): F[List[Scope.Dependencies]] =
     for {
       buildRootDir <- workspaceAlg.buildRootDir(buildRoot)
       maybeSbtVersion <- getSbtVersion(buildRootDir)
-      lines <- addStewardPluginTemporarily(buildRootDir, maybeSbtVersion).surround {
-        val commands = Nel.of(crossStewardDependencies, reloadPlugins, stewardDependencies)
+      metaBuilds <- metaBuildsCount(buildRootDir)
+      lines <- addStewardPluginTemporarily(buildRootDir, maybeSbtVersion, metaBuilds).surround {
+        val commands = Nel.of(crossStewardDependencies) ++
+          List.fill(metaBuilds)(List(reloadPlugins, stewardDependencies)).flatten
         sbt(commands, buildRootDir)
       }
       dependencies = parser.parseDependencies(lines)
@@ -65,7 +77,8 @@ final class SbtAlg[F[_]](config: Config)(implicit
 
   private def addStewardPluginTemporarily(
       buildRootDir: File,
-      maybeSbtVersion: Option[Version]
+      maybeSbtVersion: Option[Version],
+      metaBuilds: Int
   ): Resource[F, Unit] =
     for {
       _ <- Resource.unit[F]
@@ -74,8 +87,9 @@ final class SbtAlg[F[_]](config: Config)(implicit
         case _                                => "1_3_11"
       }
       plugin <- Resource.eval(stewardPlugin(pluginVersion))
-      _ <- fileAlg.createTemporarily(buildRootDir / project, plugin)
-      _ <- fileAlg.createTemporarily(buildRootDir / project / project, plugin)
+      _ <- List
+        .iterate(buildRootDir / project, metaBuilds + 1)(_ / project)
+        .collectFold(fileAlg.createTemporarily(_, plugin))
     } yield ()
 
   private def stewardPlugin(version: String): F[FileData] = {
diff --git a/modules/core/src/main/scala/org/scalasteward/core/edit/update/ScannerAlg.scala b/modules/core/src/main/scala/org/scalasteward/core/edit/update/ScannerAlg.scala
index 3c1d9aa5..97acf020 100644
--- a/modules/core/src/main/scala/org/scalasteward/core/edit/update/ScannerAlg.scala
+++ b/modules/core/src/main/scala/org/scalasteward/core/edit/update/ScannerAlg.scala
@@ -18,8 +18,6 @@ package org.scalasteward.core.edit.update
 
 import better.files.File
 import cats.effect.Concurrent
-import cats.syntax.functor._
-import com.github.arturopala.gitignore.GitIgnore
 import fs2.Stream
 import org.scalasteward.core.data.{Dependency, Repo, Version}
 import org.scalasteward.core.edit.update.data.{ModulePosition, VersionPosition}
@@ -58,35 +56,19 @@ final class ScannerAlg[F[_]](implicit
       .compile
       .foldMonoid
 
-  private def getGitIgnore(repoDir: File): F[Option[GitIgnore]] = {
-    val gitIgnore = repoDir / ".gitignore"
-    fileAlg.readFile(gitIgnore).map(_.map(GitIgnore.parse))
-  }
-
   private def findPathsContaining(
       repo: Repo,
       config: RepoConfig,
       string: String
-  ): Stream[F, FileData] = {
-    def fileFilter(repoDir: File, maybeGitIgnore: Option[GitIgnore]) = (file: File) => {
-      val path = repoDir.relativize(file).toString
-      val notDotGit = !path.startsWith(".git/")
-      val onlyKeepConfiguredExtensions =
-        config.updates.fileExtensionsOrDefault.exists(path.endsWith)
-      val allowedByGitIgnore = maybeGitIgnore.map(_.isAllowed(path)).getOrElse(true)
-      val cond = notDotGit &&
-        onlyKeepConfiguredExtensions &&
-        allowedByGitIgnore
-      Option.when(cond)(path)
+  ): Stream[F, FileData] =
+    Stream.eval(workspaceAlg.repoDir(repo)).flatMap { repoDir =>
+      val fileFilter = (file: File) => {
+        val path = repoDir.relativize(file).toString
+        val cond = !path.startsWith(".git/") &&
+          config.updates.fileExtensionsOrDefault.exists(path.endsWith)
+        Option.when(cond)(path)
+      }
+      val contentFilter = (content: String) => Some(content).filter(_.contains(string))
+      fileAlg.findFiles(repoDir, fileFilter, contentFilter).map(FileData.tupled)
     }
-    val contentFilter = (content: String) => Some(content).filter(_.contains(string))
-
-    for {
-      repoDir <- Stream.eval(workspaceAlg.repoDir(repo))
-      maybeRootGitIgnore <- Stream.eval(getGitIgnore(repoDir))
-      files <- fileAlg
-        .findFiles(repoDir, fileFilter(repoDir, maybeRootGitIgnore), contentFilter)
-        .map(FileData.tupled)
-    } yield files
-  }
 }
diff --git a/modules/core/src/main/scala/org/scalasteward/core/io/ProcessAlg.scala b/modules/core/src/main/scala/org/scalasteward/core/io/ProcessAlg.scala
index 025f36cb..1d7ac2f8 100644
--- a/modules/core/src/main/scala/org/scalasteward/core/io/ProcessAlg.scala
+++ b/modules/core/src/main/scala/org/scalasteward/core/io/ProcessAlg.scala
@@ -24,9 +24,7 @@ import org.scalasteward.core.io.process.{Args, SlurpOption, SlurpOptions}
 import org.scalasteward.core.util.Nel
 import org.typelevel.log4cats.Logger
 
-final class ProcessAlg[F[_]](config: ProcessCfg)(
-    private[io] val execImpl: Args => F[List[String]]
-) {
+final class ProcessAlg[F[_]](config: ProcessCfg)(execImpl: Args => F[List[String]]) {
   def exec(
       command: Nel[String],
       workingDirectory: File,
diff --git a/project/Dependencies.scala b/project/Dependencies.scala
index 7a917fe1..e5938e7a 100644
--- a/project/Dependencies.scala
+++ b/project/Dependencies.scala
@@ -20,7 +20,6 @@ object Dependencies {
   val disciplineMunit = "org.typelevel" %% "discipline-munit" % "1.0.9"
   val fs2Core = "co.fs2" %% "fs2-core" % "3.6.1"
   val fs2Io = "co.fs2" %% "fs2-io" % fs2Core.revision
-  val gitignore = "com.github.arturopala" %% "gitignore" % "0.4.0"
   val http4sCore = "org.http4s" %% "http4s-core" % "1.0.0-M39"
   val http4sCirce = "org.http4s" %% "http4s-circe" % http4sCore.revision
   val http4sClient = "org.http4s" %% "http4s-client" % http4sCore.revision


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 a96fe2cc..80441af8 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
@@ -55,6 +55,8 @@ class BuildToolDispatcherTest extends FunSuite {
         ),
         Log("Get dependencies in . from sbt"),
         Cmd("read", s"$repoDir/project/build.properties"),
+        Cmd("test", "-d", s"$repoDir/project"),
+        Cmd("test", "-d", s"$repoDir/project/project"),
         Cmd("read", "classpath:StewardPlugin_1_0_0.scala"),
         Cmd("write", s"$repoDir/project/scala-steward-StewardPlugin_1_0_0.scala"),
         Cmd("write", s"$repoDir/project/project/scala-steward-StewardPlugin_1_0_0.scala"),
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 5b779fb5..b00014bc 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
@@ -15,15 +15,18 @@ class SbtAlgTest extends FunSuite {
   private val workspace = workspaceAlg.rootDir.unsafeRunSync()
 
   test("getDependencies") {
-    val repo = Repo("typelevel", "cats")
+    val repo = Repo("sbt-alg", "test-1")
     val buildRoot = BuildRoot(repo, ".")
     val repoDir = workspaceAlg.repoDir(repo).unsafeRunSync()
-    val files = Map(repoDir / "project" / "build.properties" -> "sbt.version=1.3.6")
-    val initial = MockState.empty.copy(files = files)
+    val initial = MockState.empty
+      .addFiles(repoDir / "project" / "build.properties" -> "sbt.version=1.3.11")
+      .unsafeRunSync()
     val state = sbtAlg.getDependencies(buildRoot).runS(initial).unsafeRunSync()
     val expected = initial.copy(
       trace = Vector(
         Cmd("read", s"$repoDir/project/build.properties"),
+        Cmd("test", "-d", s"$repoDir/project"),
+        Cmd("test", "-d", s"$repoDir/project/project"),
         Cmd("read", "classpath:StewardPlugin_1_3_11.scala"),
         Cmd("write", s"$repoDir/project/scala-steward-StewardPlugin_1_3_11.scala"),
         Cmd("write", s"$repoDir/project/project/scala-steward-StewardPlugin_1_3_11.scala"),
diff --git a/modules/core/src/test/scala/org/scalasteward/core/buildtool/scalacli/ScalaCliAlgTest.scala b/modules/core/src/test/scala/org/scalasteward/core/buildtool/scalacli/ScalaCliAlgTest.scala
index 4245484f..d9b64fd0 100644
--- a/modules/core/src/test/scala/org/scalasteward/core/buildtool/scalacli/ScalaCliAlgTest.scala
+++ b/modules/core/src/test/scala/org/scalasteward/core/buildtool/scalacli/ScalaCliAlgTest.scala
@@ -49,9 +49,9 @@ class ScalaCliAlgTest extends CatsEffectSuite {
           repoDir.toString
         ),
         Cmd("read", s"$sbtBuildDir/project/build.properties"),
+        Cmd("test", "-d", s"$sbtBuildDir/project"),
         Cmd("read", "classpath:StewardPlugin_1_3_11.scala"),
         Cmd("write", s"$sbtBuildDir/project/scala-steward-StewardPlugin_1_3_11.scala"),
-        Cmd("write", s"$sbtBuildDir/project/project/scala-steward-StewardPlugin_1_3_11.scala"),
         Cmd(
           sbtBuildDir.toString,
           "firejail",
@@ -63,9 +63,8 @@ class ScalaCliAlgTest extends CatsEffectSuite {
           "-Dsbt.color=false",
           "-Dsbt.log.noformat=true",
           "-Dsbt.supershell=false",
-          s";$crossStewardDependencies;$reloadPlugins;$stewardDependencies"
+          s";$crossStewardDependencies"
         ),
-        Cmd("rm", "-rf", s"$sbtBuildDir/project/project/scala-steward-StewardPlugin_1_3_11.scala"),
         Cmd("rm", "-rf", s"$sbtBuildDir/project/scala-steward-StewardPlugin_1_3_11.scala"),
         Cmd("rm", "-rf", s"$sbtBuildDir")
       )
diff --git a/modules/core/src/test/scala/org/scalasteward/core/edit/EditAlgTest.scala b/modules/core/src/test/scala/org/scalasteward/core/edit/EditAlgTest.scala
index 8e68975b..d6487ae0 100644
--- a/modules/core/src/test/scala/org/scalasteward/core/edit/EditAlgTest.scala
+++ b/modules/core/src/test/scala/org/scalasteward/core/edit/EditAlgTest.scala
@@ -27,26 +27,21 @@ class EditAlgTest extends FunSuite {
     val update = ("org.typelevel".g % "cats-core".a % "1.2.0" %> "1.3.0").single
     val file1 = repoDir / "build.sbt"
     val file2 = repoDir / "project/Dependencies.scala"
-    val gitignore = repoDir / ".gitignore"
 
     val state = MockState.empty
-      .addFiles(file1 -> """val catsVersion = "1.2.0"""", file2 -> "", gitignore -> "")
+      .addFiles(file1 -> """val catsVersion = "1.2.0"""", file2 -> "")
       .flatMap(editAlg.applyUpdate(data, update).runS)
       .unsafeRunSync()
 
     val expected = MockState.empty.copy(
       trace = Vector(
-        Cmd("read", gitignore.pathAsString),
         Cmd("test", "-f", repoDir.pathAsString),
-        Cmd("test", "-f", gitignore.pathAsString),
         Cmd("test", "-f", file1.pathAsString),
         Cmd("read", file1.pathAsString),
         Cmd("test", "-f", (repoDir / "project").pathAsString),
         Cmd("test", "-f", file2.pathAsString),
         Cmd("read", file2.pathAsString),
-        Cmd("read", gitignore.pathAsString),
         Cmd("test", "-f", repoDir.pathAsString),
-        Cmd("test", "-f", gitignore.pathAsString),
         Cmd("test", "-f", file1.pathAsString),
         Cmd("read", file1.pathAsString),
         Cmd("test", "-f", (repoDir / "project").pathAsString),
@@ -56,7 +51,7 @@ class EditAlgTest extends FunSuite {
         Cmd("write", file1.pathAsString),
         Cmd(gitStatus(repoDir))
       ),
-      files = Map(file1 -> """val catsVersion = "1.3.0"""", file2 -> "", gitignore -> "")
+      files = Map(file1 -> """val catsVersion = "1.3.0"""", file2 -> "")
     )
 
     assertEquals(state, expected)
@@ -70,47 +65,30 @@ class EditAlgTest extends FunSuite {
     val data = RepoData(repo, cache, RepoConfig.empty)
     val repoDir = workspaceAlg.repoDir(repo).unsafeRunSync()
     val update = ("org.scalameta".g % "scalafmt-core".a % "2.0.0" %> "2.1.0").single
-    val gitignore = repoDir / ".gitignore"
     val scalafmtConf = repoDir / scalafmtConfName
     val scalafmtConfContent = """maxColumn = 100
                                 |version = 2.0.0
                                 |align.openParenCallSite = false
                                 |""".stripMargin
     val buildSbt = repoDir / "build.sbt"
-    val target = repoDir / "target"
-    // this file should not be read because it's under target which is git ignored
-    val targetScalaFile = target / "SomeFile.scala"
 
     val state = MockState.empty
-      .addFiles(
-        scalafmtConf -> scalafmtConfContent,
-        buildSbt -> "",
-        gitignore -> "target/",
-        targetScalaFile -> ""
-      )
+      .addFiles(scalafmtConf -> scalafmtConfContent, buildSbt -> "")
       .flatMap(editAlg.applyUpdate(data, update).runS)
       .unsafeRunSync()
 
     val expected = MockState.empty.copy(
       trace = Vector(
-        Cmd("read", gitignore.pathAsString),
         Cmd("test", "-f", repoDir.pathAsString),
-        Cmd("test", "-f", gitignore.pathAsString),
         Cmd("test", "-f", scalafmtConf.pathAsString),
         Cmd("read", scalafmtConf.pathAsString),
         Cmd("test", "-f", buildSbt.pathAsString),
         Cmd("read", buildSbt.pathAsString),
-        Cmd("test", "-f", target.pathAsString),
-        Cmd("test", "-f", targetScalaFile.pathAsString),
-        Cmd("read", gitignore.pathAsString),
         Cmd("test", "-f", repoDir.pathAsString),
-        Cmd("test", "-f", gitignore.pathAsString),
         Cmd("test", "-f", scalafmtConf.pathAsString),
         Cmd("read", scalafmtConf.pathAsString),
         Cmd("test", "-f", buildSbt.pathAsString),
         Cmd("read", buildSbt.pathAsString),
-        Cmd("test", "-f", target.pathAsString),
-        Cmd("test", "-f", targetScalaFile.pathAsString),
         Cmd("read", scalafmtConf.pathAsString),
         Cmd("write", scalafmtConf.pathAsString),
         Cmd(
@@ -131,9 +109,7 @@ class EditAlgTest extends FunSuite {
             |version = 2.1.0
             |align.openParenCallSite = false
             |""".stripMargin,
-        buildSbt -> "",
-        gitignore -> "target/",
-        targetScalaFile -> ""
+        buildSbt -> ""
       )
     )
 
diff --git a/modules/core/src/test/scala/org/scalasteward/core/io/MockProcessAlg.scala b/modules/core/src/test/scala/org/scalasteward/core/io/MockProcessAlg.scala
index edf6119d..388db237 100644
--- a/modules/core/src/test/scala/org/scalasteward/core/io/MockProcessAlg.scala
+++ b/modules/core/src/test/scala/org/scalasteward/core/io/MockProcessAlg.scala
@@ -8,16 +8,18 @@ import org.scalasteward.core.mock.MockEff
 object MockProcessAlg {
   def create(config: ProcessCfg): ProcessAlg[MockEff] =
     new ProcessAlg(config)({ args =>
-      Kleisli { ctx =>
+      Kleisli { x =>
         for {
-          state <- ctx.get
+          state <- x.get
           cmd = args.workingDirectory.map(_.toString).toList ++ args.command.toList
-          _ <- ctx.set(state.exec(cmd, args.extraEnv: _*))
-          res <- state.commandOutputs.get(args.command.toList) match {
-            case Some(output)               => IO.fromEither(output)
-            case None if state.execCommands => ProcessAlgTest.ioProcessAlg.execImpl(args)
-            case None                       => IO.pure(List.empty)
-          }
+          newState = state.exec(cmd, args.extraEnv: _*)
+          res <- x
+            .set(newState)
+            .flatMap { _ =>
+              state.commandOutputs
+                .getOrElse(args.command.toList, Right(List.empty))
+                .fold(err => IO.raiseError(err), a => IO.pure(a))
+            }
         } yield res
       }
     })
diff --git a/modules/core/src/test/scala/org/scalasteward/core/mock/MockState.scala b/modules/core/src/test/scala/org/scalasteward/core/mock/MockState.scala
index 1aef3445..61f2c89d 100644
--- a/modules/core/src/test/scala/org/scalasteward/core/mock/MockState.scala
+++ b/modules/core/src/test/scala/org/scalasteward/core/mock/MockState.scala
@@ -11,7 +11,6 @@ import org.scalasteward.core.mock.MockState.TraceEntry.{Cmd, Log}
 final case class MockState(
     trace: Vector[TraceEntry],
     commandOutputs: Map[List[String], Either[Throwable, List[String]]],
-    execCommands: Boolean,
     files: Map[File, String],
     uris: Map[Uri, String],
     clientResponses: HttpApp[MockEff]
@@ -42,7 +41,6 @@ object MockState {
     MockState(
       trace = Vector.empty,
       commandOutputs = Map.empty,
-      execCommands = false,
       files = Map.empty,
       uris = Map.empty,
       clientResponses = HttpApp.notFound