Repository: scala-steward-org/scala-steward
Pull request #1990 (2021-03-03 14:00:49)

Prevent overtaking updates
Removes overtaking updates as described in https://github.com/scala-steward-org/scala-steward/issues/129#issuecomment-789731187.

codecov[bot]: # [Codecov](https://codecov.io/gh/scala-steward-org/scala-steward/pull/1990?src=pr&el=h1) Report
> Merging [#1990](https://codecov.io/gh/scala-steward-org/scala-steward/pull/1990?src=pr&el=desc) (9cbbf53) into [master](https://codecov.io/gh/scala-steward-org/scala-steward/commit/5b9859f3a9e70acfee02da6582f3ba63751a3070?el=desc) (5b9859f) will **increase** coverage by `0.16%`.
> The diff coverage is `100.00%`.

[![Impacted file tree graph](https://codecov.io/gh/scala-steward-org/scala-steward/pull/1990/graphs/tree.svg?width=650&height=150&src=pr&token=udzMsc1Dne)](https://codecov.io/gh/scala-steward-org/scala-steward/pull/1990?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master    #1990      +/-   ##
==========================================
+ Coverage   78.52%   78.68%   +0.16%     
==========================================
  Files         130      129       -1     
  Lines        2249     2257       +8     
  Branches       54       52       -2     
==========================================
+ Hits         1766     1776      +10     
+ Misses        483      481       -2     
```


| [Impacted Files](https://codecov.io/gh/scala-steward-org/scala-steward/pull/1990?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [...cala/org/scalasteward/core/update/PruningAlg.scala](https://codecov.io/gh/scala-steward-org/scala-steward/pull/1990/diff?src=pr&el=tree#diff-bW9kdWxlcy9jb3JlL3NyYy9tYWluL3NjYWxhL29yZy9zY2FsYXN0ZXdhcmQvY29yZS91cGRhdGUvUHJ1bmluZ0FsZy5zY2FsYQ==) | `91.42% <100.00%> (+2.90%)` | :arrow_up: |
| [...la-2.12/org/scalasteward/mill/plugin/package.scala](https://codecov.io/gh/scala-steward-org/scala-steward/pull/1990/diff?src=pr&el=tree#diff-bW9kdWxlcy9taWxsLXBsdWdpbi9zcmMvbWFpbi9zY2FsYS0yLjEyL29yZy9zY2FsYXN0ZXdhcmQvbWlsbC9wbHVnaW4vcGFja2FnZS5zY2FsYQ==) | | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/scala-steward-org/scala-steward/pull/1990?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/scala-steward-org/scala-steward/pull/1990?src=pr&el=footer). Last update [5b9859f...9cbbf53](https://codecov.io/gh/scala-steward-org/scala-steward/pull/1990?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/modules/core/src/main/scala/org/scalasteward/core/update/PruningAlg.scala b/modules/core/src/main/scala/org/scalasteward/core/update/PruningAlg.scala
index d2a95be7..fb118731 100644
--- a/modules/core/src/main/scala/org/scalasteward/core/update/PruningAlg.scala
+++ b/modules/core/src/main/scala/org/scalasteward/core/update/PruningAlg.scala
@@ -62,7 +62,9 @@ final class PruningAlg[F[_]](implicit
     val depsWithoutResolvers = dependencies.map(_.value).distinct
     for {
       _ <- logger.info(s"Find updates for ${repo.show}")
-      updates0 <- updateAlg.findUpdates(dependencies, repoConfig, None)
+      updates0 <- updateAlg
+        .findUpdates(dependencies, repoConfig, None)
+        .map(removeOvertakingUpdates(depsWithoutResolvers, _))
       updateStates0 <- findAllUpdateStates(repo, repoCache, depsWithoutResolvers, updates0)
       outdatedDeps = collectOutdatedDependencies(updateStates0)
       (updateStates1, updates1) <- {
@@ -170,6 +172,21 @@ object PruningAlg {
       FilterAlg.isScalaDependencyIgnored(info.dependency, ignoreScalaDependency) ||
       FilterAlg.isDependencyConfigurationIgnored(info.dependency)
 
+  def removeOvertakingUpdates(
+      dependencies: List[Dependency],
+      updates: List[Update.Single]
+  ): List[Update.Single] =
+    updates.filterNot { update =>
+      dependencies.exists { dependency =>
+        dependency.groupId === update.groupId &&
+        dependency.artifactId === update.artifactId && {
+          val dependencyVersion = Version(dependency.version)
+          dependencyVersion > Version(update.currentVersion) &&
+          dependencyVersion <= Version(update.nextVersion)
+        }
+      }
+    }
+
   def collectOutdatedDependencies(updateStates: List[UpdateState]): List[DependencyOutdated] =
     updateStates.collect { case state: DependencyOutdated => state }
 }


Test patch:
diff --git a/modules/core/src/test/scala/org/scalasteward/core/update/PruningAlgTest.scala b/modules/core/src/test/scala/org/scalasteward/core/update/PruningAlgTest.scala
index 02dd5efd..697a0009 100644
--- a/modules/core/src/test/scala/org/scalasteward/core/update/PruningAlgTest.scala
+++ b/modules/core/src/test/scala/org/scalasteward/core/update/PruningAlgTest.scala
@@ -2,7 +2,10 @@ package org.scalasteward.core.update
 
 import io.circe.parser.decode
 import munit.FunSuite
-import org.scalasteward.core.data.RepoData
+import org.scalasteward.core.TestInstances.dummyRepoCache
+import org.scalasteward.core.TestSyntax._
+import org.scalasteward.core.data.Resolver.MavenRepository
+import org.scalasteward.core.data.{DependencyInfo, RepoData, Scope}
 import org.scalasteward.core.mock.MockContext._
 import org.scalasteward.core.mock.MockContext.context.pruningAlg
 import org.scalasteward.core.mock.MockState
@@ -389,4 +392,35 @@ class PruningAlgTest extends FunSuite {
     )
     assertEquals(state, expected)
   }
+
+  test("needsAttention: no overtaking updates") {
+    val repo = Repo("pruning-test", "repo5")
+    val repoCache = dummyRepoCache.copy(dependencyInfos =
+      List(
+        Scope(
+          List(
+            DependencyInfo("org.scala-lang" % "scala-library" % "2.12.13", List("build.sbt")),
+            DependencyInfo("org.scala-lang" % "scala-library" % "2.13.5", List("build.sbt"))
+          ),
+          List(MavenRepository("public", "https://repo5.org/maven/", None))
+        )
+      )
+    )
+    val data = RepoData(repo, repoCache, RepoConfig.empty)
+    val versionsFile =
+      config.workspace / "store/versions/v2/https/repo5.org/maven/org/scala-lang/scala-library/versions.json"
+    val versionsContent =
+      s"""|{
+          |  "updatedAt" : 9999999999999,
+          |  "versions" : [
+          |    "2.12.13",
+          |    "2.13.5"
+          |  ]
+          |}""".stripMargin
+    (for {
+      initial <- MockState.empty.addFiles(versionsFile -> versionsContent)
+      // This should not propose an update from 2.12.13 to 2.13.5.
+      (_, updates) <- pruningAlg.needsAttention(data).runA(initial)
+    } yield assertEquals(updates, List.empty)).unsafeRunSync()
+  }
 }