mirror of https://github.com/sbt/sbt.git
Bump io
This new version of io breaks source and binary compatibility everywhere that uses the register(path: Path, depth: Int) method that is defined on a few interfaces because I changed the signature to register(glob: Glob). I had to convert to using a glob everywhere that register was called. I also noticed a number of places where we were calling .asFile on a file. This is redundant because asFile is an extension method on File that just returns the underlying file. Finally, I share the IOSyntax trait from io in AllSyntax. There was more or less a TODO suggesting this change. The one hairy part is the existence of the Alternative class. This class has unfortunately somehow made it into the sbt package object. While I doubt many plugins are using this, it doesn't seem worth breaking binary compatibility to get rid of it. The issue is that while Alternative is defined private[sbt], the alternative method in IOSyntax is public, so I can't get rid of Alternative without breaking binary compatibility. I'm not deprecating Alternative for now because the sbtProj still has xfatal warnings on. I think in many, if not most, cases, the Alternative class makes the code more confusing as is often the case with custom operators. The confusion is mitigated if the abstraction is used only in the file in which it's defined.
This commit is contained in:
parent
ffa69ea5d6
commit
f7f7addff7
|
|
@ -27,10 +27,8 @@ final class FileTreeViewConfig private (
|
|||
) => FileEventMonitor[FileCacheEntry]
|
||||
)
|
||||
object FileTreeViewConfig {
|
||||
private implicit class RepositoryOps(val repository: FileTreeRepository[FileCacheEntry]) {
|
||||
def register(sources: Seq[WatchSource]): Unit = sources foreach { s =>
|
||||
repository.register(s.base.toPath, if (s.recursive) Integer.MAX_VALUE else 0)
|
||||
}
|
||||
private implicit class SourceOps(val s: WatchSource) extends AnyVal {
|
||||
def toGlob: Glob = Glob(s.base, AllPassFilter, if (s.recursive) Integer.MAX_VALUE else 0)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -76,14 +74,16 @@ object FileTreeViewConfig {
|
|||
val ioLogger: sbt.io.WatchLogger = msg => logger.debug(msg.toString)
|
||||
FileEventMonitor.antiEntropy(
|
||||
new WatchServiceBackedObservable(
|
||||
WatchState.empty(Watched.createWatchService(), sources),
|
||||
WatchState.empty(sources.map(_.toGlob), Watched.createWatchService()),
|
||||
delay,
|
||||
FileCacheEntry.default,
|
||||
closeService = true,
|
||||
ioLogger
|
||||
),
|
||||
antiEntropy,
|
||||
ioLogger
|
||||
ioLogger,
|
||||
50.milliseconds,
|
||||
10.seconds
|
||||
)
|
||||
}
|
||||
)
|
||||
|
|
@ -104,14 +104,20 @@ object FileTreeViewConfig {
|
|||
sources: Seq[WatchSource],
|
||||
logger: Logger
|
||||
) => {
|
||||
repository.register(sources)
|
||||
sources.view.map(_.toGlob).foreach(repository.register)
|
||||
val copied = new Observable[FileCacheEntry] {
|
||||
override def addObserver(observer: Observer[FileCacheEntry]): Int =
|
||||
repository.addObserver(observer)
|
||||
override def removeObserver(handle: Int): Unit = repository.removeObserver(handle)
|
||||
override def close(): Unit = {} // Don't close the underlying observable
|
||||
}
|
||||
FileEventMonitor.antiEntropy(copied, antiEntropy, msg => logger.debug(msg.toString))
|
||||
FileEventMonitor.antiEntropy(
|
||||
copied,
|
||||
antiEntropy,
|
||||
msg => logger.debug(msg.toString),
|
||||
50.milliseconds,
|
||||
10.seconds
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
|
|
@ -159,18 +165,20 @@ object FileTreeViewConfig {
|
|||
pollingInterval: FiniteDuration,
|
||||
pollingSources: Seq[WatchSource],
|
||||
): FileTreeViewConfig = FileTreeViewConfig(
|
||||
() => FileTreeRepository.hybrid(FileCacheEntry.default, pollingSources: _*),
|
||||
() => FileTreeRepository.hybrid(FileCacheEntry.default, pollingSources.map(_.toGlob): _*),
|
||||
(
|
||||
repository: HybridPollingFileTreeRepository[FileCacheEntry],
|
||||
sources: Seq[WatchSource],
|
||||
logger: Logger
|
||||
) => {
|
||||
repository.register(sources)
|
||||
sources.view.map(_.toGlob).foreach(repository.register)
|
||||
FileEventMonitor
|
||||
.antiEntropy(
|
||||
repository.toPollingObservable(pollingInterval, sources, NullWatchLogger),
|
||||
repository.toPollingRepository(pollingInterval, NullWatchLogger),
|
||||
antiEntropy,
|
||||
msg => logger.debug(msg.toString)
|
||||
msg => logger.debug(msg.toString),
|
||||
50.milliseconds,
|
||||
10.seconds
|
||||
)
|
||||
}
|
||||
)
|
||||
|
|
|
|||
|
|
@ -16,7 +16,8 @@ import sbt.Watched._
|
|||
import sbt.WatchedSpec._
|
||||
import sbt.internal.FileCacheEntry
|
||||
import sbt.io.FileEventMonitor.Event
|
||||
import sbt.io.{ FileEventMonitor, IO, TypedPath }
|
||||
import sbt.io._
|
||||
import sbt.io.syntax._
|
||||
import sbt.util.Logger
|
||||
|
||||
import scala.collection.mutable
|
||||
|
|
@ -26,7 +27,7 @@ class WatchedSpec extends FlatSpec with Matchers {
|
|||
object Defaults {
|
||||
private val fileTreeViewConfig = FileTreeViewConfig.default(50.millis)
|
||||
def config(
|
||||
sources: Seq[WatchSource],
|
||||
globs: Seq[Glob],
|
||||
fileEventMonitor: Option[FileEventMonitor[FileCacheEntry]] = None,
|
||||
logger: Logger = NullLogger,
|
||||
handleInput: InputStream => Action = _ => Ignore,
|
||||
|
|
@ -35,9 +36,17 @@ class WatchedSpec extends FlatSpec with Matchers {
|
|||
triggeredMessage: (TypedPath, Int) => Option[String] = (_, _) => None,
|
||||
watchingMessage: Int => Option[String] = _ => None
|
||||
): WatchConfig = {
|
||||
val monitor = fileEventMonitor.getOrElse(
|
||||
fileTreeViewConfig.newMonitor(fileTreeViewConfig.newDataView(), sources, logger)
|
||||
)
|
||||
val monitor = fileEventMonitor.getOrElse {
|
||||
val fileTreeRepository = FileTreeRepository.default(FileCacheEntry.default)
|
||||
globs.foreach(fileTreeRepository.register)
|
||||
FileEventMonitor.antiEntropy(
|
||||
fileTreeRepository,
|
||||
50.millis,
|
||||
m => logger.debug(m.toString),
|
||||
50.milliseconds,
|
||||
100.milliseconds
|
||||
)
|
||||
}
|
||||
WatchConfig.default(
|
||||
logger = logger,
|
||||
monitor,
|
||||
|
|
@ -55,13 +64,13 @@ class WatchedSpec extends FlatSpec with Matchers {
|
|||
override def read(): Int = -1
|
||||
}
|
||||
"Watched.watch" should "stop" in IO.withTemporaryDirectory { dir =>
|
||||
val config = Defaults.config(sources = Seq(WatchSource(dir.toRealPath)))
|
||||
val config = Defaults.config(globs = Seq(dir.toRealPath.toGlob))
|
||||
Watched.watch(NullInputStream, () => Right(true), config) shouldBe CancelWatch
|
||||
}
|
||||
it should "trigger" in IO.withTemporaryDirectory { dir =>
|
||||
val triggered = new AtomicBoolean(false)
|
||||
val config = Defaults.config(
|
||||
sources = Seq(WatchSource(dir.toRealPath)),
|
||||
globs = Seq(dir.toRealPath ** AllPassFilter),
|
||||
preWatch = (count, _) => if (count == 2) CancelWatch else Ignore,
|
||||
onWatchEvent = _ => { triggered.set(true); Trigger },
|
||||
watchingMessage = _ => {
|
||||
|
|
@ -77,7 +86,7 @@ class WatchedSpec extends FlatSpec with Matchers {
|
|||
val foo = realDir.toPath.resolve("foo")
|
||||
val bar = realDir.toPath.resolve("bar")
|
||||
val config = Defaults.config(
|
||||
sources = Seq(WatchSource(realDir)),
|
||||
globs = Seq(realDir ** AllPassFilter),
|
||||
preWatch = (count, _) => if (count == 2) CancelWatch else Ignore,
|
||||
onWatchEvent = e => if (e.entry.typedPath.toPath == foo) Trigger else Ignore,
|
||||
triggeredMessage = (tp, _) => { queue += tp; None },
|
||||
|
|
@ -92,7 +101,7 @@ class WatchedSpec extends FlatSpec with Matchers {
|
|||
val foo = realDir.toPath.resolve("foo")
|
||||
val bar = realDir.toPath.resolve("bar")
|
||||
val config = Defaults.config(
|
||||
sources = Seq(WatchSource(realDir)),
|
||||
globs = Seq(realDir ** AllPassFilter),
|
||||
preWatch = (count, _) => if (count == 3) CancelWatch else Ignore,
|
||||
onWatchEvent = _ => Trigger,
|
||||
triggeredMessage = (tp, _) => { queue += tp; None },
|
||||
|
|
@ -113,7 +122,7 @@ class WatchedSpec extends FlatSpec with Matchers {
|
|||
it should "halt on error" in IO.withTemporaryDirectory { dir =>
|
||||
val halted = new AtomicBoolean(false)
|
||||
val config = Defaults.config(
|
||||
sources = Seq(WatchSource(dir.toRealPath)),
|
||||
globs = Seq(dir.toRealPath ** AllPassFilter),
|
||||
preWatch = (_, lastStatus) => if (lastStatus) Ignore else { halted.set(true); HandleError }
|
||||
)
|
||||
Watched.watch(NullInputStream, () => Right(false), config) shouldBe HandleError
|
||||
|
|
@ -121,7 +130,7 @@ class WatchedSpec extends FlatSpec with Matchers {
|
|||
}
|
||||
it should "reload" in IO.withTemporaryDirectory { dir =>
|
||||
val config = Defaults.config(
|
||||
sources = Seq(WatchSource(dir.toRealPath)),
|
||||
globs = Seq(dir.toRealPath ** AllPassFilter),
|
||||
preWatch = (_, _) => Ignore,
|
||||
onWatchEvent = _ => Reload,
|
||||
watchingMessage = _ => { new File(dir, "file").createNewFile(); None }
|
||||
|
|
|
|||
|
|
@ -628,12 +628,15 @@ object Defaults extends BuildCommon {
|
|||
watchOnTermination := Watched.onTermination,
|
||||
watchConfig := {
|
||||
val sources = watchTransitiveSources.value ++ watchProjectTransitiveSources.value
|
||||
val globs = sources.map(
|
||||
s => Glob(s.base, s.includeFilter -- s.excludeFilter, if (s.recursive) Int.MaxValue else 0)
|
||||
)
|
||||
val wm = watchingMessage.?.value
|
||||
.map(w => (count: Int) => Some(w(WatchState.empty(sources).withCount(count))))
|
||||
.map(w => (count: Int) => Some(w(WatchState.empty(globs).withCount(count))))
|
||||
.getOrElse(watchStartMessage.value)
|
||||
val tm = triggeredMessage.?.value
|
||||
.map(
|
||||
tm => (_: TypedPath, count: Int) => Some(tm(WatchState.empty(sources).withCount(count)))
|
||||
tm => (_: TypedPath, count: Int) => Some(tm(WatchState.empty(globs).withCount(count)))
|
||||
)
|
||||
.getOrElse(watchTriggeredMessage.value)
|
||||
val logger = watchLogger.value
|
||||
|
|
@ -1203,14 +1206,14 @@ object Defaults extends BuildCommon {
|
|||
def artifactPathSetting(art: SettingKey[Artifact]): Initialize[File] =
|
||||
Def.setting {
|
||||
val f = artifactName.value
|
||||
(crossTarget.value / f(
|
||||
crossTarget.value / f(
|
||||
ScalaVersion(
|
||||
(scalaVersion in artifactName).value,
|
||||
(scalaBinaryVersion in artifactName).value
|
||||
),
|
||||
projectID.value,
|
||||
art.value
|
||||
)).asFile
|
||||
)
|
||||
}
|
||||
|
||||
def artifactSetting: Initialize[Artifact] =
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ object Opts {
|
|||
"sonatype-staging",
|
||||
"https://oss.sonatype.org/service/local/staging/deploy/maven2"
|
||||
)
|
||||
val mavenLocalFile = Resolver.file("Local Repository", userHome / ".m2" / "repository" asFile)(
|
||||
val mavenLocalFile = Resolver.file("Local Repository", userHome / ".m2" / "repository")(
|
||||
Resolver.defaultPatterns
|
||||
)
|
||||
val sbtSnapshots = Resolver.bintrayRepo("sbt", "maven-snapshots")
|
||||
|
|
|
|||
|
|
@ -11,11 +11,16 @@ package internal
|
|||
import java.io.File
|
||||
import java.net.URI
|
||||
import BuildLoader._
|
||||
import sbt.internal.io.Alternatives._
|
||||
import sbt.internal.util.Types.{ const, idFun }
|
||||
import sbt.util.Logger
|
||||
import sbt.librarymanagement.ModuleID
|
||||
|
||||
private[internal] object Alternatives {
|
||||
private[internal] implicit class Alternative[A, B](val f: A => Option[B]) {
|
||||
def |(g: A => Option[B]): A => Option[B] = (a: A) => f(a) orElse g(a)
|
||||
}
|
||||
}
|
||||
import Alternatives.Alternative
|
||||
final class MultiHandler[S, T](
|
||||
builtIn: S => Option[T],
|
||||
root: Option[S => Option[T]],
|
||||
|
|
|
|||
|
|
@ -329,5 +329,5 @@ object BuildStreams {
|
|||
def refTarget(ref: ResolvedReference, fallbackBase: File, data: Settings[Scope]): File =
|
||||
refTarget(GlobalScope.copy(project = Select(ref)), fallbackBase, data)
|
||||
def refTarget(scope: Scope, fallbackBase: File, data: Settings[Scope]): File =
|
||||
(Keys.target in scope get data getOrElse outputDirectory(fallbackBase).asFile) / StreamsDirectory
|
||||
(Keys.target in scope get data getOrElse outputDirectory(fallbackBase)) / StreamsDirectory
|
||||
}
|
||||
|
|
|
|||
|
|
@ -339,7 +339,7 @@ defaults
|
|||
|
||||
def sbtRCs(s: State): Seq[File] =
|
||||
(Path.userHome / sbtrc) ::
|
||||
(s.baseDir / sbtrc asFile) ::
|
||||
(s.baseDir / sbtrc) ::
|
||||
Nil
|
||||
|
||||
val CrossCommand = "+"
|
||||
|
|
|
|||
|
|
@ -11,8 +11,8 @@ import java.util.Optional
|
|||
|
||||
import sbt.Stamped
|
||||
import sbt.internal.inc.ExternalLookup
|
||||
import sbt.io.syntax.File
|
||||
import sbt.io.{ FileTreeRepository, FileTreeDataView, TypedPath }
|
||||
import sbt.io.syntax._
|
||||
import sbt.io.{ AllPassFilter, FileTreeDataView, FileTreeRepository, TypedPath }
|
||||
import xsbti.compile._
|
||||
import xsbti.compile.analysis.Stamp
|
||||
|
||||
|
|
@ -34,28 +34,31 @@ private[sbt] object ExternalHooks {
|
|||
}
|
||||
view match {
|
||||
case r: FileTreeRepository[FileCacheEntry] =>
|
||||
r.register(options.classesDirectory.toPath, Integer.MAX_VALUE)
|
||||
options.classpath.foreach { f =>
|
||||
r.register(f.toPath, Integer.MAX_VALUE)
|
||||
r.register(options.classesDirectory ** AllPassFilter)
|
||||
options.classpath.foreach {
|
||||
case f if f.getName.endsWith(".jar") => r.register(f.toGlob)
|
||||
case f => r.register(f ** AllPassFilter)
|
||||
}
|
||||
case _ =>
|
||||
}
|
||||
val allBinaries = new java.util.HashMap[File, Stamp]
|
||||
options.classpath.foreach { f =>
|
||||
view.listEntries(f.toPath, Integer.MAX_VALUE, _ => true) foreach { e =>
|
||||
e.value match {
|
||||
case Right(value) => allBinaries.put(e.typedPath.toPath.toFile, value.stamp)
|
||||
case _ =>
|
||||
options.classpath.foreach {
|
||||
case f if f.getName.endsWith(".jar") =>
|
||||
// This gives us the entry for the path itself, which is necessary if the path is a jar file
|
||||
// rather than a directory.
|
||||
view.listEntries(f.toGlob) foreach { e =>
|
||||
e.value match {
|
||||
case Right(value) => allBinaries.put(e.typedPath.toPath.toFile, value.stamp)
|
||||
case _ =>
|
||||
}
|
||||
}
|
||||
}
|
||||
// This gives us the entry for the path itself, which is necessary if the path is a jar file
|
||||
// rather than a directory.
|
||||
view.listEntries(f.toPath, -1, _ => true) foreach { e =>
|
||||
e.value match {
|
||||
case Right(value) => allBinaries.put(e.typedPath.toPath.toFile, value.stamp)
|
||||
case _ =>
|
||||
case f =>
|
||||
view.listEntries(f ** "*.jar") foreach { e =>
|
||||
e.value match {
|
||||
case Right(value) => allBinaries.put(e.typedPath.toPath.toFile, value.stamp)
|
||||
case _ =>
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val lookup = new ExternalLookup {
|
||||
|
|
|
|||
|
|
@ -8,14 +8,13 @@
|
|||
package sbt.internal
|
||||
|
||||
import java.io.IOException
|
||||
import java.nio.file.Path
|
||||
|
||||
import sbt.BasicCommandStrings.ContinuousExecutePrefix
|
||||
import sbt.Keys._
|
||||
import sbt._
|
||||
import sbt.io.FileTreeDataView.Entry
|
||||
import sbt.io.syntax.File
|
||||
import sbt.io.{ FileFilter, FileTreeDataView, FileTreeRepository }
|
||||
import sbt.io._
|
||||
import sbt.io.syntax._
|
||||
|
||||
private[sbt] object FileManagement {
|
||||
private[sbt] def defaultFileTreeView: Def.Initialize[Task[FileTreeViewConfig]] = Def.task {
|
||||
|
|
@ -33,14 +32,30 @@ private[sbt] object FileManagement {
|
|||
} else FileTreeViewConfig.sbt1_2_compat(pollInterval.value, watchAntiEntropy.value)
|
||||
}
|
||||
private[sbt] implicit class FileTreeDataViewOps[+T](val fileTreeDataView: FileTreeDataView[T]) {
|
||||
def register(path: Path, maxDepth: Int): Either[IOException, Boolean] = {
|
||||
def register(glob: Glob): Either[IOException, Boolean] = {
|
||||
fileTreeDataView match {
|
||||
case r: FileTreeRepository[T] => r.register(path, maxDepth)
|
||||
case r: FileTreeRepository[T] => r.register(glob)
|
||||
case _ => Right(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private def entryFilter(
|
||||
include: FileFilter,
|
||||
exclude: FileFilter
|
||||
): Entry[FileCacheEntry] => Boolean = { e =>
|
||||
val tp = e.typedPath
|
||||
/*
|
||||
* The TypedPath has the isDirectory and isFile properties embedded. By overriding
|
||||
* these methods in java.io.File, FileFilters may be applied without needing to
|
||||
* stat the file (which is expensive) for isDirectory and isFile checks.
|
||||
*/
|
||||
val file = new java.io.File(tp.toPath.toString) {
|
||||
override def isDirectory: Boolean = tp.isDirectory
|
||||
override def isFile: Boolean = tp.isFile
|
||||
}
|
||||
include.accept(file) && !exclude.accept(file)
|
||||
}
|
||||
private[sbt] def collectFiles(
|
||||
dirs: ScopedTaskable[Seq[File]],
|
||||
filter: ScopedTaskable[FileFilter],
|
||||
|
|
@ -51,51 +66,35 @@ private[sbt] object FileManagement {
|
|||
val view = fileTreeView.value
|
||||
val include = filter.toTask.value
|
||||
val ex = excludes.toTask.value
|
||||
val sourceFilter: Entry[FileCacheEntry] => Boolean = (entry: Entry[FileCacheEntry]) => {
|
||||
val typedPath = entry.typedPath
|
||||
val file = new java.io.File(typedPath.toPath.toString) {
|
||||
override def isDirectory: Boolean = typedPath.isDirectory
|
||||
override def isFile: Boolean = typedPath.isFile
|
||||
}
|
||||
include.accept(file) && !ex.accept(file)
|
||||
}
|
||||
val sourceFilter: Entry[FileCacheEntry] => Boolean = entryFilter(include, ex)
|
||||
sourceDirs.flatMap { dir =>
|
||||
view.register(dir.toPath, maxDepth = Integer.MAX_VALUE)
|
||||
view.register(dir ** AllPassFilter)
|
||||
view
|
||||
.listEntries(dir.toPath, maxDepth = Integer.MAX_VALUE, sourceFilter)
|
||||
.flatMap(e => e.value.toOption.map(Stamped.file(e.typedPath, _)))
|
||||
.listEntries(dir.toPath ** AllPassFilter)
|
||||
.flatMap {
|
||||
case e if sourceFilter(e) => e.value.toOption.map(Stamped.file(e.typedPath, _))
|
||||
case _ => None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private[sbt] def appendBaseSources: Seq[Def.Setting[Task[Seq[File]]]] = Seq(
|
||||
unmanagedSources := {
|
||||
val sources = unmanagedSources.value
|
||||
val f = (includeFilter in unmanagedSources).value
|
||||
val include = (includeFilter in unmanagedSources).value
|
||||
val excl = (excludeFilter in unmanagedSources).value
|
||||
val baseDir = baseDirectory.value
|
||||
val view = fileTreeView.value
|
||||
if (sourcesInBase.value) {
|
||||
view.register(baseDir.toPath, maxDepth = 0)
|
||||
view.register(baseDir.toPath * AllPassFilter)
|
||||
val filter: Entry[FileCacheEntry] => Boolean = entryFilter(include, excl)
|
||||
sources ++
|
||||
view
|
||||
.listEntries(
|
||||
baseDir.toPath,
|
||||
maxDepth = 0,
|
||||
e => {
|
||||
val tp = e.typedPath
|
||||
/*
|
||||
* The TypedPath has the isDirectory and isFile properties embedded. By overriding
|
||||
* these methods in java.io.File, FileFilters may be applied without needing to
|
||||
* stat the file (which is expensive) for isDirectory and isFile checks.
|
||||
*/
|
||||
val file = new java.io.File(tp.toPath.toString) {
|
||||
override def isDirectory: Boolean = tp.isDirectory
|
||||
override def isFile: Boolean = tp.isFile
|
||||
}
|
||||
f.accept(file) && !excl.accept(file)
|
||||
}
|
||||
)
|
||||
.flatMap(e => e.value.toOption.map(Stamped.file(e.typedPath, _)))
|
||||
.listEntries(baseDir * AllPassFilter)
|
||||
.flatMap {
|
||||
case e if filter(e) => e.value.toOption.map(Stamped.file(e.typedPath, _))
|
||||
case _ => None
|
||||
}
|
||||
} else sources
|
||||
}
|
||||
)
|
||||
|
|
|
|||
|
|
@ -9,12 +9,12 @@ object Dependencies {
|
|||
val baseScalaVersion = scala212
|
||||
|
||||
// sbt modules
|
||||
private val ioVersion = "1.3.0-M5"
|
||||
private val ioVersion = "1.3.0-M7"
|
||||
private val utilVersion = "1.3.0-M5"
|
||||
private val lmVersion =
|
||||
sys.props.get("sbt.build.lm.version") match {
|
||||
case Some(version) => version
|
||||
case _ => "1.3.0-M1"
|
||||
case _ => "1.3.0-M1"
|
||||
}
|
||||
private val zincVersion = "1.3.0-M2"
|
||||
|
||||
|
|
@ -34,13 +34,13 @@ object Dependencies {
|
|||
val lmOrganization =
|
||||
sys.props.get("sbt.build.lm.organization") match {
|
||||
case Some(impl) => impl
|
||||
case _ => "org.scala-sbt"
|
||||
case _ => "org.scala-sbt"
|
||||
}
|
||||
|
||||
val lmModuleName =
|
||||
sys.props.get("sbt.build.lm.moduleName") match {
|
||||
case Some(impl) => impl
|
||||
case _ => "librarymanagement-ivy"
|
||||
case _ => "librarymanagement-ivy"
|
||||
}
|
||||
|
||||
lmOrganization %% lmModuleName % lmVersion
|
||||
|
|
@ -98,7 +98,8 @@ object Dependencies {
|
|||
|
||||
def addSbtLmCore(p: Project): Project =
|
||||
addSbtModule(p, sbtLmPath, "lmCore", libraryManagementCore)
|
||||
def addSbtLmImpl(p: Project): Project = addSbtModule(p, sbtLmPath, "lmImpl", libraryManagementImpl)
|
||||
def addSbtLmImpl(p: Project): Project =
|
||||
addSbtModule(p, sbtLmPath, "lmImpl", libraryManagementImpl)
|
||||
|
||||
def addSbtCompilerInterface(p: Project): Project =
|
||||
addSbtModule(p, sbtZincPath, "compilerInterface212", compilerInterface)
|
||||
|
|
|
|||
|
|
@ -7,15 +7,12 @@
|
|||
|
||||
package sbt
|
||||
|
||||
// Todo share this this io.syntax
|
||||
private[sbt] trait IOSyntax0 extends IOSyntax1 {
|
||||
implicit def alternative[A, B](f: A => Option[B]): Alternative[A, B] =
|
||||
g => a => f(a) orElse g(a)
|
||||
implicit def alternative[A, B](f: A => Option[B]): Alternative[A, B] = new Alternative[A, B] {
|
||||
override def |(g: A => Option[B]): A => Option[B] = (a: A) => f(a) orElse g(a)
|
||||
}
|
||||
}
|
||||
private[sbt] trait IOSyntax1 extends sbt.io.IOSyntax
|
||||
private[sbt] trait Alternative[A, B] {
|
||||
def |(g: A => Option[B]): A => Option[B]
|
||||
}
|
||||
|
||||
private[sbt] trait IOSyntax1 {
|
||||
implicit def singleFileFinder(file: File): sbt.io.PathFinder = sbt.io.PathFinder(file)
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue