diff --git a/build.mill b/build.mill index 5e9f3e2a..5193be87 100644 --- a/build.mill +++ b/build.mill @@ -8,14 +8,16 @@ import mill._, scalalib._, scalanativelib._, publish._ import mill.scalalib.api.ZincWorkerUtil import com.github.lolgab.mill.mima._ import de.tobiasroeser.mill.vcs.version.VcsVersion +import mill.scalalib.scalafmt.ScalafmtModule + val communityBuildDottyVersion = sys.props.get("dottyVersion").toList val scala213Version = "2.13.14" val scalaVersions = Seq( - "3.3.1", - "2.12.17", + "3.3.3", + "2.12.19", scala213Version ) ++ communityBuildDottyVersion @@ -26,6 +28,7 @@ object Deps { val sourcecode = ivy"com.lihaoyi::sourcecode::0.4.2" val utest = ivy"com.lihaoyi::utest::0.8.4" val expecty = ivy"com.eed3si9n.expecty::expecty::0.16.0" + val collectionCompact = ivy"org.scala-lang.modules::scala-collection-compat:2.12.0" def scalaReflect(scalaVersion: String) = ivy"org.scala-lang:scala-reflect:$scalaVersion" def scalaLibrary(version: String) = ivy"org.scala-lang:scala-library:${version}" } @@ -39,7 +42,12 @@ trait AcyclicModule extends ScalaModule { } def compileIvyDeps = acyclicDep def scalacPluginIvyDeps = acyclicDep - def scalacOptions = super.scalacOptions() ++ acyclicOptions() + def scalacOptions = super.scalacOptions() ++ acyclicOptions() ++ Seq( + "-deprecation", + "-feature", + "-language:implicitConversions", + "-language:higherKinds", + ) } trait SafeDeps extends ScalaModule { @@ -111,8 +119,8 @@ trait OsLibModule } } -trait OsModule extends OsLibModule { outer => - def ivyDeps = Agg(Deps.geny) +trait OsModule extends OsLibModule with ScalafmtModule { outer => + def ivyDeps = Agg(Deps.geny, Deps.collectionCompact) override def compileIvyDeps = T { val scalaReflectOpt = Option.when(!ZincWorkerUtil.isDottyOrScala3(scalaVersion()))( Deps.scalaReflect(scalaVersion()) @@ -165,6 +173,7 @@ trait OsModule extends OsLibModule { outer => } } + object os extends Module { object jvm extends Cross[OsJvmModule](scalaVersions) diff --git a/os/src/GlobInterpolator.scala b/os/src/GlobInterpolator.scala index 73a11c0a..4c7f3edb 100644 --- a/os/src/GlobInterpolator.scala +++ b/os/src/GlobInterpolator.scala @@ -2,8 +2,8 @@ package os object GlobInterpolator { class Interped(parts: Seq[String]) { - def unapplySeq(s: String) = { - val Seq(head, tail @ _*) = parts.map(java.util.regex.Pattern.quote) + def unapplySeq(s: String): Option[List[String]] = { + val Seq(head, tail @ _*) = parts.map(java.util.regex.Pattern.quote): @unchecked val regex = head + tail.map("(.*)" + _).mkString regex.r.unapplySeq(s) diff --git a/os/src/ListOps.scala b/os/src/ListOps.scala index 05257407..5306b13e 100644 --- a/os/src/ListOps.scala +++ b/os/src/ListOps.scala @@ -17,7 +17,7 @@ import java.nio.file.attribute.BasicFileAttributes object list extends Function1[Path, IndexedSeq[Path]] { def apply(src: Path, sort: Boolean = true): IndexedSeq[Path] = { val arr = stream(src).toArray[Path] - if (sort) arr.sorted + if (sort) arr.sorted.toIndexedSeq else arr } def apply(src: Path): IndexedSeq[Path] = apply(src, true).toIndexedSeq @@ -53,7 +53,7 @@ object list extends Function1[Path, IndexedSeq[Path]] { * saving time as compared to filtering them after the fact. * * By default, the paths are returned as a pre-order traversal: the enclosing - * folder is occurs first before any of it's contents. You can pass in `preOrder = + * folder occurs first before any of its contents. You can pass in `preOrder = * false` to turn it into a post-order traversal, such that the enclosing folder * occurs last after all it's contents. * @@ -76,12 +76,12 @@ object walk { * you want `preOrder` to be `true` so the folder gets * created first. * - * @param followLinks Whether or not to follow symlinks while walking; defaults + * @param followLinks Whether to follow symlinks while walking; defaults * to false * * @param maxDepth The max depth of the tree you wish to walk; defaults to unlimited * - * @param includeTarget Whether or not to include the given path as part of the walk. + * @param includeTarget Whether to include the given path as part of the walk. * If `true`, does not raise an error if the given path is a * simple file and not a folder */ @@ -109,12 +109,12 @@ object walk { * you want `preOrder` to be `true` so the folder gets * created first. * - * @param followLinks Whether or not to follow symlinks while walking; defaults + * @param followLinks Whether to follow symlinks while walking; defaults * to false * * @param maxDepth The max depth of the tree you wish to walk; defaults to unlimited * - * @param includeTarget Whether or not to include the given path as part of the walk. + * @param includeTarget Whether to include the given path as part of the walk. * If `true`, does not raise an error if the given path is a * simple file and not a folder */ @@ -145,12 +145,12 @@ object walk { * you want `preOrder` to be `true` so the folder gets * created first. * - * @param followLinks Whether or not to follow symlinks while walking; defaults + * @param followLinks Whether to follow symlinks while walking; defaults * to false * * @param maxDepth The max depth of the tree you wish to walk; defaults to unlimited * - * @param includeTarget Whether or not to include the given path as part of the walk. + * @param includeTarget Whether to include the given path as part of the walk. * If `true`, does not raise an error if the given path is a * simple file and not a folder */ @@ -179,12 +179,12 @@ object walk { * you want `preOrder` to be `true` so the folder gets * created first. * - * @param followLinks Whether or not to follow symlinks while walking; defaults + * @param followLinks Whether to follow symlinks while walking; defaults * to false * * @param maxDepth The max depth of the tree you wish to walk; defaults to unlimited * - * @param includeTarget Whether or not to include the given path as part of the walk. + * @param includeTarget Whether to include the given path as part of the walk. * If `true`, does not raise an error if the given path is a * simple file and not a folder */ @@ -228,7 +228,7 @@ object walk { // rather than relying on `walkFileTree`, because `walkFileTree` // does the unintuitive thing when the `path` being walked is a // symlink to a directory (it just returns the symlink path and - // does not walking) + // does not walk) val ds = Files.newDirectoryStream(pathNIO) val iter = ds.iterator() try { diff --git a/os/src/Path.scala b/os/src/Path.scala index e135c4c5..deb8acd7 100644 --- a/os/src/Path.scala +++ b/os/src/Path.scala @@ -2,7 +2,7 @@ package os import java.net.URI import java.nio.file.Paths -import collection.JavaConverters._ +import scala.jdk.CollectionConverters._ import scala.language.implicitConversions import acyclic.skipped import os.PathError.{InvalidSegment, NonCanonicalLiteral} @@ -212,7 +212,7 @@ object BasePath { } } def chunkify(s: java.nio.file.Path) = { - import collection.JavaConverters._ + import scala.jdk.CollectionConverters._ s.iterator().asScala.map(_.toString).filter(_ != ".").filter(_ != "").toArray } } diff --git a/os/src/ProcessOps.scala b/os/src/ProcessOps.scala index 6175e87c..5bdc3124 100644 --- a/os/src/ProcessOps.scala +++ b/os/src/ProcessOps.scala @@ -1,6 +1,6 @@ package os -import collection.JavaConverters._ +import scala.jdk.CollectionConverters._ import java.lang.ProcessBuilder.Redirect import os.SubProcess.InputStream import java.io.IOException diff --git a/os/src/ReadWriteOps.scala b/os/src/ReadWriteOps.scala index 62b8c0be..cffdc86b 100644 --- a/os/src/ReadWriteOps.scala +++ b/os/src/ReadWriteOps.scala @@ -56,7 +56,7 @@ object write { ) = { checker.value.onWrite(target) - import collection.JavaConverters._ + import scala.jdk.CollectionConverters._ val permArray: Array[FileAttribute[_]] = if (perms == null) Array.empty else Array(PosixFilePermissions.asFileAttribute(perms.toSet())) diff --git a/os/src/SubProcess.scala b/os/src/SubProcess.scala index 9f624819..680e077f 100644 --- a/os/src/SubProcess.scala +++ b/os/src/SubProcess.scala @@ -51,7 +51,7 @@ sealed trait ProcessLike extends java.lang.AutoCloseable { /** * Wait up to `millis` for the [[ProcessLike]] to terminate and all stdout and stderr - * from the subprocess to be handled. By default waits indefinitely; if a time + * from the subprocess to be handled. By default, waits indefinitely; if a time * limit is given, explicitly destroys the [[ProcessLike]] if it has not completed by * the time the timeout has occurred. * @@ -152,7 +152,7 @@ class SubProcess( * @param async set this to `true` if you do not want to wait on the subprocess exiting * @param shutdownGracePeriod use this to override the default wait time for the subprocess * to gracefully exit before destroying it forcibly. Defaults to the `shutdownGracePeriod` - * that was used to spawned the process, but can be set to 0 + * that was used to spawn the process, but can be set to 0 * (i.e. force exit immediately) or -1 (i.e. never force exit) * or anything in between. Typically defaults to 100 milliseconds. */ @@ -183,7 +183,7 @@ class SubProcess( /** * Alias for [[destroy]] */ - def close() = wrapped.destroy() + def close(): Unit = wrapped.destroy() /** * Wait up to `millis` for the subprocess to terminate, by default waits @@ -296,7 +296,7 @@ object SubProcess { out.toByteArray } - override def close() = wrapped.close() + override def close(): Unit = wrapped.close() } } @@ -314,7 +314,7 @@ class ProcessPipeline( /** * String representation of the pipeline. */ - def commandString = processes.map(_.wrapped.toString).mkString(" | ") + def commandString: String = processes.map(_.wrapped.toString).mkString(" | ") private[os] val brokenPipeHandler: Option[Thread] = brokenPipeQueue.map { queue => new Thread( @@ -326,7 +326,7 @@ class ProcessPipeline( if (brokenPipeIndex == processes.length) { // Special case signaling finished pipeline pipelineRunning = false } else { - processes(brokenPipeIndex).destroyForcibly() + processes(brokenPipeIndex).destroy(shutdownGracePeriod = 0) } } new Thread( @@ -354,9 +354,7 @@ class ProcessPipeline( */ override def exitCode(): Int = { if (pipefail) - processes.map(_.exitCode()) - .filter(_ != 0) - .headOption + processes.map(_.exitCode()).find(_ != 0) .getOrElse(0) else processes.last.exitCode() @@ -383,7 +381,7 @@ class ProcessPipeline( * All processes in the pipeline are force-destroyed. */ override def destroyForcibly(): Unit = { - processes.foreach(_.destroyForcibly()) + processes.foreach(_.destroy(shutdownGracePeriod = 0)) } /** diff --git a/os/src/ZipOps.scala b/os/src/ZipOps.scala index a62d7d49..968c2018 100644 --- a/os/src/ZipOps.scala +++ b/os/src/ZipOps.scala @@ -4,7 +4,8 @@ import java.net.URI import java.nio.file.{FileSystem, FileSystems, Files} import java.nio.file.attribute.{BasicFileAttributeView, FileTime, PosixFilePermissions} import java.util.zip.{ZipEntry, ZipFile, ZipInputStream, ZipOutputStream} -import scala.collection.JavaConverters._ +import scala.jdk.CollectionConverters._ + import scala.util.matching.Regex object zip { diff --git a/os/test/src-jvm/ZipOpJvmTests.scala b/os/test/src-jvm/ZipOpJvmTests.scala index dfe4bad2..8ab629db 100644 --- a/os/test/src-jvm/ZipOpJvmTests.scala +++ b/os/test/src-jvm/ZipOpJvmTests.scala @@ -5,7 +5,7 @@ import utest._ import java.nio.file.attribute.FileTime import java.nio.file.{Files, Paths} import java.util.zip.ZipFile -import scala.collection.JavaConverters._ +import scala.jdk.CollectionConverters._ object ZipOpJvmTests extends TestSuite { diff --git a/os/watch/src/WatchServiceWatcher.scala b/os/watch/src/WatchServiceWatcher.scala index 39f22b3d..ec731515 100644 --- a/os/watch/src/WatchServiceWatcher.scala +++ b/os/watch/src/WatchServiceWatcher.scala @@ -8,7 +8,7 @@ import java.nio.file.StandardWatchEventKinds.{ENTRY_CREATE, ENTRY_DELETE, ENTRY_ import com.sun.nio.file.{ExtendedWatchEventModifier, SensitivityWatchEventModifier} import scala.collection.mutable -import collection.JavaConverters._ +import scala.jdk.CollectionConverters._ import scala.util.Properties.isWin class WatchServiceWatcher(