From 5616dc9b46e033b39d0df12e42173ee1c875cee4 Mon Sep 17 00:00:00 2001 From: Guillaume Galy Date: Sat, 14 Jul 2018 03:20:19 +0200 Subject: Issue #314; port sbt-updates to mill (#340) * Implement basic dependency resolution * Implement basic dependency versions resolution (Maven only) * refactor dependency updates code * add resolution of updated dependencies * remove dependency on locally-built coursier * dependency updates output formatting * Add 'allowPreRelease' option * start adding tests * Add more tests * Add documentation * Cleanup code * rewrite version parser to use fastparse --- .../metadata/MetadataLoaderFactoryTests.scala | 64 ++++++++ .../dependency/updates/UpdatesFinderTests.scala | 173 +++++++++++++++++++++ .../dependency/versions/VersionTests.scala | 139 +++++++++++++++++ 3 files changed, 376 insertions(+) create mode 100644 scalalib/test/src/mill/scalalib/dependency/metadata/MetadataLoaderFactoryTests.scala create mode 100644 scalalib/test/src/mill/scalalib/dependency/updates/UpdatesFinderTests.scala create mode 100644 scalalib/test/src/mill/scalalib/dependency/versions/VersionTests.scala (limited to 'scalalib/test') diff --git a/scalalib/test/src/mill/scalalib/dependency/metadata/MetadataLoaderFactoryTests.scala b/scalalib/test/src/mill/scalalib/dependency/metadata/MetadataLoaderFactoryTests.scala new file mode 100644 index 00000000..8187976c --- /dev/null +++ b/scalalib/test/src/mill/scalalib/dependency/metadata/MetadataLoaderFactoryTests.scala @@ -0,0 +1,64 @@ +/* + * This file contains code originally published under the following license: + * + * Copyright (c) 2012, Roman Timushev + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package mill.scalalib.dependency.metadata + +import coursier.Fetch.Content +import coursier.core.{Artifact, Module, Project, Repository} +import coursier.ivy.IvyRepository +import coursier.maven.MavenRepository +import scalaz.{EitherT, Monad} +import utest._ + +object MetadataLoaderFactoryTests extends TestSuite { + + val tests = Tests { + 'mavenRepository - { + val mavenRepo = MavenRepository("https://repo1.maven.org/maven2") + assertMatch(MetadataLoaderFactory(mavenRepo)) { + case Some(MavenMetadataLoader(`mavenRepo`)) => + } + } + 'ivyRepository - { + val ivyRepo = IvyRepository( + "https://dl.bintray.com/sbt/sbt-plugin-releases/" + coursier.ivy.Pattern.default.string, + dropInfoAttributes = true) + assertMatch(MetadataLoaderFactory(ivyRepo)) { case None => } + } + 'otherRepository - { + val otherRepo = new CustomRepository + assertMatch(MetadataLoaderFactory(otherRepo)) { case None => } + } + } + + case class CustomRepository() extends Repository { + override def find[F[_]](module: Module, version: String, fetch: Content[F])( + implicit F: Monad[F]): EitherT[F, String, (Artifact.Source, Project)] = + ??? + } +} diff --git a/scalalib/test/src/mill/scalalib/dependency/updates/UpdatesFinderTests.scala b/scalalib/test/src/mill/scalalib/dependency/updates/UpdatesFinderTests.scala new file mode 100644 index 00000000..7b6e6e36 --- /dev/null +++ b/scalalib/test/src/mill/scalalib/dependency/updates/UpdatesFinderTests.scala @@ -0,0 +1,173 @@ +/* + * This file contains code originally published under the following license: + * + * Copyright (c) 2012, Roman Timushev + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package mill.scalalib.dependency.updates + +import mill.scalalib.dependency.versions.{DependencyVersions, Version} +import utest._ + +object UpdatesFinderTests extends TestSuite { + + private def updates(current: String, + available: Seq[String], + allowPreRelease: Boolean) = { + val dependency = coursier.Dependency( + coursier.Module("com.example.organization", "example-artifact"), + current) + val currentVersion = Version(current) + val allVersions = available.map(Version(_)).toSet + + UpdatesFinder + .findUpdates(DependencyVersions(dependency, currentVersion, allVersions), + allowPreRelease) + .updates + .map(_.toString) + } + + val available = Seq( + "0.9.9-SNAPSHOT", + "0.9.9-M3", + "0.9.9", + "1.0.0-SNAPSHOT", + "1.0.0-M2", + "1.0.0-M3", + "1.0.0", + "1.0.1-SNAPSHOT", + "1.0.1-M3", + "1.0.1" + ) + + val tests = Tests { + + 'snapshotArtifacts - { + val u = updates("1.0.0-SNAPSHOT", available, allowPreRelease = false) + val pu = updates("1.0.0-SNAPSHOT", available, allowPreRelease = true) + + 'noOldStableVersions - { + assert(!u.contains("0.9.9")) + } + 'noOldMilestones - { + assert(!u.contains("0.9.9-M3")) + } + 'noOldSnapshots - { + assert(!u.contains("0.9.9-SNAPSHOT")) + } + 'noCurrentMilestones - { + assert(!u.contains("1.0.0-M3")) + } + 'noCurrentSnapshot - { + assert(!u.contains("1.0.0-SNAPSHOT")) + } + 'stableUpdates - { + assert(u.contains("1.0.0") && u.contains("1.0.1")) + } + 'milestoneUpdates - { + assert(u.contains("1.0.1-M3")) + } + 'snapshotUpdates - { + assert(u.contains("1.0.1-SNAPSHOT")) + } + 'noDifferencesRegardingOptionalPreReleases - { + assert(u == pu) + } + } + + 'milestoneArtifacts - { + val u = updates("1.0.0-M2", available, allowPreRelease = false) + val pu = updates("1.0.0-M2", available, allowPreRelease = true) + + 'noOldStableVersions - { + assert(!u.contains("0.9.9")) + } + 'noOldSnapshots - { + assert(!u.contains("0.9.9-SNAPSHOT")) + } + 'noOldMilestones - { + assert(!u.contains("0.9.9-M3")) + } + 'noCurrentSnapshot - { + assert(!u.contains("1.0.0-SNAPSHOT")) + } + 'currentMilestones - { + assert(u.contains("1.0.0-M3")) + } + 'stableUpdates - { + assert(u.contains("1.0.1")) + } + 'noSnapshotUpdates - { + assert(!u.contains("1.0.1-SNAPSHOT")) + } + 'milestoneUpdates - { + assert(u.contains("1.0.1-M3")) + } + 'noDifferencesRegardingOptionalPreReleases - { + assert(u == pu) + } + } + + 'stableArtifacts - { + val u = updates("1.0.0", available, allowPreRelease = false) + val pu = updates("1.0.0", available, allowPreRelease = true) + + 'noOldStableVersions - { + assert(!u.contains("0.9.9")) + assert(!pu.contains("0.9.9")) + } + 'noOldSnapshots - { + assert(!u.contains("0.9.9-SNAPSHOT")) + assert(!pu.contains("0.9.9-SNAPSHOT")) + } + 'noOldMilestones - { + assert(!u.contains("0.9.9-M3")) + assert(!pu.contains("0.9.9-M3")) + } + 'noCurrentSnapshot - { + assert(!u.contains("1.0.0-SNAPSHOT")) + assert(!pu.contains("1.0.0-SNAPSHOT")) + } + 'noCurrentMilestones - { + assert(!u.contains("1.0.0-M3")) + assert(!pu.contains("1.0.0-M3")) + } + 'stableUpdates - { + assert(u.contains("1.0.1")) + assert(pu.contains("1.0.1")) + } + 'noSnapshotUpdates - { + assert(!u.contains("1.0.1-SNAPSHOT")) + assert(!pu.contains("1.0.1-SNAPSHOT")) + } + 'noMilestoneUpdates - { + assert(!u.contains("1.0.1-M3")) + } + 'milestoneUpdatesWhenAllowingPreReleases - { + assert(pu.contains("1.0.1-M3")) + } + } + } +} diff --git a/scalalib/test/src/mill/scalalib/dependency/versions/VersionTests.scala b/scalalib/test/src/mill/scalalib/dependency/versions/VersionTests.scala new file mode 100644 index 00000000..8bc1a992 --- /dev/null +++ b/scalalib/test/src/mill/scalalib/dependency/versions/VersionTests.scala @@ -0,0 +1,139 @@ +/* + * This file contains code originally published under the following license: + * + * Copyright (c) 2012, Roman Timushev + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +package mill.scalalib.dependency.versions + +import utest._ +import fastparse.core.Parsed + +object VersionTests extends TestSuite { + + val tests = Tests { + 'versionsClassification - { + 'ReleaseVersion - { + List("1.0.0", "1.0.0.Final", "1.0.0-FINAL", "1.0.0.RELEASE") foreach { + rel => + assertMatch(Version(rel)) { + case ReleaseVersion(List(1, 0, 0)) => + } + } + } + 'PreReleaseVersion - { + assertMatch(Version("1.0.0-alpha.1")) { + case PreReleaseVersion(List(1, 0, 0), List("alpha", "1")) => + } + } + 'PreReleaseBuildVersion - { + assertMatch(Version("1.0.0-alpha.1+build.10")) { + case PreReleaseBuildVersion(List(1, 0, 0), + List("alpha", "1"), + List("build", "10")) => + } + } + 'BuildVersion - { + assertMatch(Version("1.0.0+build.10")) { + case BuildVersion(List(1, 0, 0), List("build", "10")) => + } + } + } + + 'semverVersionsOrdering - { + import scala.Ordered._ + + val v = List( + "invalid", + "1.0.0-20131213005945", + "1.0.0-alpha", + "1.0.0-alpha.1", + "1.0.0-beta.2", + "1.0.0-beta.11", + "1.0.0-rc.1", + "1.0.0-rc.1+build.1", + "1.0.0", + "1.0.0+0.3.7", + "1.33.7+build", + "1.33.7+build.2.b8f12d7", + "1.33.7+build.11.e0f985a", + "2.0.M5b", + "2.0.M6-SNAP9", + "2.0.M6-SNAP23", + "2.0.M6-SNAP23a" + ).map(Version.apply) + val pairs = v.tails.flatMap { + case h :: t => t.map((h, _)) + case Nil => List.empty + } + pairs.foreach { + case (a, b) => + assert(a < b) + assert(b > a) + } + } + + 'parser - { + + Symbol("parse 1.0.5") - { + assertMatch(VersionParser.parse("1.0.5")) { + case Parsed.Success((Seq(1, 0, 5), Seq(), Seq()), _) => + } + } + + Symbol("parse 1.0.M3") - { + assertMatch(VersionParser.parse("1.0.M3")) { + case Parsed.Success((Seq(1, 0), Seq("M3"), Seq()), _) => + } + } + Symbol("parse 1.0.3m") - { + assertMatch(VersionParser.parse("1.0.3m")) { + case Parsed.Success((Seq(1, 0), Seq("3m"), Seq()), _) => + } + } + Symbol("parse 1.0.3m.4") - { + assertMatch(VersionParser.parse("1.0.3m.4")) { + case Parsed.Success((Seq(1, 0), Seq("3m", "4"), Seq()), _) => + } + } + Symbol("parse 9.1-901-1.jdbc4") - { + assertMatch(VersionParser.parse("9.1-901-1.jdbc4")) { + case Parsed + .Success((Seq(9, 1), Seq("901", "1", "jdbc4"), Seq()), _) => + } + } + Symbol("parse 1.33.7+build/11.e0f985a") - { + assertMatch(VersionParser.parse("1.33.7+build/11.e0f985a")) { + case Parsed.Success((Seq(1, 33, 7), Seq(), Seq("build/11", "e0f985a")), _) => + } + } + Symbol("parse 9.1-901-1.jdbc4+build/11.e0f985a") - { + assertMatch(VersionParser.parse("9.1-901-1.jdbc4+build/11.e0f985a")) { + case Parsed.Success((Seq(9, 1), Seq("901", "1", "jdbc4"), Seq("build/11", "e0f985a")), _) => + } + } + } + } +} -- cgit v1.2.3