Rename FileCacheEntry to FileAttributes

I decided that FileCacheEntry was a bad name because the methods did not
necessarily have anything to do with caching. Moreover, because it is
exposed in a public interface, it shouldn't be in the internal package.
This commit is contained in:
Ethan Atkins 2019-03-20 10:38:26 -07:00
parent be94b25d68
commit d231d7d9ec
8 changed files with 61 additions and 61 deletions

View File

@ -10,7 +10,7 @@ package sbt
import java.io.{ File => JFile } import java.io.{ File => JFile }
import java.nio.file.Path import java.nio.file.Path
import sbt.internal.FileCacheEntry import sbt.internal.FileAttributes
import sbt.internal.inc.{ EmptyStamp, Stamper } import sbt.internal.inc.{ EmptyStamp, Stamper }
import sbt.io.TypedPath import sbt.io.TypedPath
import xsbti.compile.analysis.Stamp import xsbti.compile.analysis.Stamp
@ -30,7 +30,7 @@ private[sbt] trait Stamped {
*/ */
private[sbt] object Stamped { private[sbt] object Stamped {
type File = JFile with Stamped type File = JFile with Stamped
private[sbt] def file(typedPath: TypedPath, entry: FileCacheEntry): JFile with Stamped = private[sbt] def file(typedPath: TypedPath, entry: FileAttributes): JFile with Stamped =
new StampedFileImpl(typedPath, entry.stamp) new StampedFileImpl(typedPath, entry.stamp)
/** /**

View File

@ -22,7 +22,7 @@ import sbt.internal.io.{ EventMonitor, Source, WatchState }
import sbt.internal.util.Types.const import sbt.internal.util.Types.const
import sbt.internal.util.complete.{ DefaultParsers, Parser } import sbt.internal.util.complete.{ DefaultParsers, Parser }
import sbt.internal.util.{ AttributeKey, JLine } import sbt.internal.util.{ AttributeKey, JLine }
import sbt.internal.{ FileCacheEntry, LegacyWatched } import sbt.internal.{ FileAttributes, LegacyWatched }
import sbt.io._ import sbt.io._
import sbt.util.{ Level, Logger } import sbt.util.{ Level, Logger }
@ -144,7 +144,7 @@ object Watched {
private[sbt] def onEvent( private[sbt] def onEvent(
sources: Seq[WatchSource], sources: Seq[WatchSource],
projectSources: Seq[WatchSource] projectSources: Seq[WatchSource]
): FileCacheEntry.Event => Watched.Action = ): FileAttributes.Event => Watched.Action =
event => event =>
if (sources.exists(_.accept(event.path))) Watched.Trigger if (sources.exists(_.accept(event.path))) Watched.Trigger
else if (projectSources.exists(_.accept(event.path))) { else if (projectSources.exists(_.accept(event.path))) {
@ -335,7 +335,7 @@ object Watched {
case _ => case _ =>
val events = config.fileEventMonitor val events = config.fileEventMonitor
.poll(10.millis) .poll(10.millis)
.map(new FileCacheEntry.EventImpl(_)) .map(new FileAttributes.EventImpl(_))
val next = events match { val next = events match {
case Seq() => (Ignore, None) case Seq() => (Ignore, None)
case Seq(head, tail @ _*) => case Seq(head, tail @ _*) =>
@ -460,7 +460,7 @@ trait WatchConfig {
* *
* @return an sbt.io.FileEventMonitor instance. * @return an sbt.io.FileEventMonitor instance.
*/ */
def fileEventMonitor: FileEventMonitor[FileCacheEntry] def fileEventMonitor: FileEventMonitor[FileAttributes]
/** /**
* A function that is periodically invoked to determine whether the watch should stop or * A function that is periodically invoked to determine whether the watch should stop or
@ -483,7 +483,7 @@ trait WatchConfig {
* @param event the detected sbt.io.FileEventMonitor.Event. * @param event the detected sbt.io.FileEventMonitor.Event.
* @return the next [[Watched.Action Action]] to run. * @return the next [[Watched.Action Action]] to run.
*/ */
def onWatchEvent(event: FileCacheEntry.Event): Watched.Action def onWatchEvent(event: FileAttributes.Event): Watched.Action
/** /**
* Transforms the state after the watch terminates. * Transforms the state after the watch terminates.
@ -539,10 +539,10 @@ object WatchConfig {
*/ */
def default( def default(
logger: Logger, logger: Logger,
fileEventMonitor: FileEventMonitor[FileCacheEntry], fileEventMonitor: FileEventMonitor[FileAttributes],
handleInput: InputStream => Watched.Action, handleInput: InputStream => Watched.Action,
preWatch: (Int, Boolean) => Watched.Action, preWatch: (Int, Boolean) => Watched.Action,
onWatchEvent: FileCacheEntry.Event => Watched.Action, onWatchEvent: FileAttributes.Event => Watched.Action,
onWatchTerminated: (Watched.Action, String, State) => State, onWatchTerminated: (Watched.Action, String, State) => State,
triggeredMessage: (Path, Int) => Option[String], triggeredMessage: (Path, Int) => Option[String],
watchingMessage: Int => Option[String] watchingMessage: Int => Option[String]
@ -557,11 +557,11 @@ object WatchConfig {
val wm = watchingMessage val wm = watchingMessage
new WatchConfig { new WatchConfig {
override def logger: Logger = l override def logger: Logger = l
override def fileEventMonitor: FileEventMonitor[FileCacheEntry] = fem override def fileEventMonitor: FileEventMonitor[FileAttributes] = fem
override def handleInput(inputStream: InputStream): Watched.Action = hi(inputStream) override def handleInput(inputStream: InputStream): Watched.Action = hi(inputStream)
override def preWatch(count: Int, lastResult: Boolean): Watched.Action = override def preWatch(count: Int, lastResult: Boolean): Watched.Action =
pw(count, lastResult) pw(count, lastResult)
override def onWatchEvent(event: FileCacheEntry.Event): Watched.Action = owe(event) override def onWatchEvent(event: FileAttributes.Event): Watched.Action = owe(event)
override def onWatchTerminated(action: Watched.Action, command: String, state: State): State = override def onWatchTerminated(action: Watched.Action, command: String, state: State): State =
owt(action, command, state) owt(action, command, state)
override def triggeredMessage(path: Path, count: Int): Option[String] = override def triggeredMessage(path: Path, count: Int): Option[String] =

View File

@ -5,39 +5,39 @@
* Licensed under Apache License 2.0 (see LICENSE) * Licensed under Apache License 2.0 (see LICENSE)
*/ */
package sbt package sbt.internal
package internal
import java.lang import java.lang
import java.nio.file.Path import java.nio.file.Path
import java.util.Optional import java.util.Optional
import sbt.Stamped
import sbt.internal.inc.{ EmptyStamp, LastModified, Stamp } import sbt.internal.inc.{ EmptyStamp, LastModified, Stamp }
import sbt.io.FileEventMonitor.{ Creation, Deletion, Update } import sbt.io.FileEventMonitor.{ Creation, Deletion, Update }
import sbt.io.{ FileEventMonitor, TypedPath } import sbt.io.{ FileEventMonitor, TypedPath }
import xsbti.compile.analysis.{ Stamp => XStamp } import xsbti.compile.analysis.{ Stamp => XStamp }
/** /**
* Represents a cache entry for a FileTreeRepository. It can be extended to add user defined * Represents the FileAttributes of a file. This will be moved to io before 1.3.0 is released.
* data to the FileTreeRepository cache.
*/ */
trait FileCacheEntry { trait FileAttributes {
def hash: Option[String] def hash: Option[String]
def lastModified: Option[Long] def lastModified: Option[Long]
} }
object FileCacheEntry { object FileAttributes {
trait Event { trait Event {
def path: Path def path: Path
def previous: Option[FileCacheEntry] def previous: Option[FileAttributes]
def current: Option[FileCacheEntry] def current: Option[FileAttributes]
} }
private[sbt] class EventImpl(event: FileEventMonitor.Event[FileCacheEntry]) extends Event { private[sbt] class EventImpl(event: FileEventMonitor.Event[FileAttributes]) extends Event {
override def path: Path = event.entry.typedPath.toPath override def path: Path = event.entry.typedPath.toPath
override def previous: Option[FileCacheEntry] = event match { override def previous: Option[FileAttributes] = event match {
case Deletion(entry, _) => entry.value.toOption case Deletion(entry, _) => entry.value.toOption
case Update(previous, _, _) => previous.value.toOption case Update(previous, _, _) => previous.value.toOption
case _ => None case _ => None
} }
override def current: Option[FileCacheEntry] = event match { override def current: Option[FileAttributes] = event match {
case Creation(entry, _) => entry.value.toOption case Creation(entry, _) => entry.value.toOption
case Update(_, current, _) => current.value.toOption case Update(_, current, _) => current.value.toOption
case _ => None case _ => None
@ -51,11 +51,11 @@ object FileCacheEntry {
((path.hashCode * 31) ^ previous.hashCode() * 31) ^ current.hashCode() ((path.hashCode * 31) ^ previous.hashCode() * 31) ^ current.hashCode()
override def toString: String = s"Event($path, $previous, $current)" override def toString: String = s"Event($path, $previous, $current)"
} }
private[sbt] def default(typedPath: TypedPath): FileCacheEntry = private[sbt] def default(typedPath: TypedPath): FileAttributes =
DelegateFileCacheEntry(Stamped.converter(typedPath)) DelegateFileAttributes(Stamped.converter(typedPath))
private[sbt] implicit class FileCacheEntryOps(val e: FileCacheEntry) extends AnyVal { private[sbt] implicit class FileAttributesOps(val e: FileAttributes) extends AnyVal {
private[sbt] def stamp: XStamp = e match { private[sbt] def stamp: XStamp = e match {
case DelegateFileCacheEntry(s) => s case DelegateFileAttributes(s) => s
case _ => case _ =>
e.hash e.hash
.map(Stamp.fromString) .map(Stamp.fromString)
@ -67,8 +67,8 @@ object FileCacheEntry {
private implicit class Equiv(val xstamp: XStamp) extends AnyVal { private implicit class Equiv(val xstamp: XStamp) extends AnyVal {
def equiv(that: XStamp): Boolean = Stamp.equivStamp.equiv(xstamp, that) def equiv(that: XStamp): Boolean = Stamp.equivStamp.equiv(xstamp, that)
} }
private case class DelegateFileCacheEntry(private val stamp: XStamp) private case class DelegateFileAttributes(private val stamp: XStamp)
extends FileCacheEntry extends FileAttributes
with XStamp { with XStamp {
override def getValueId: Int = stamp.getValueId override def getValueId: Int = stamp.getValueId
override def writeStamp(): String = stamp.writeStamp() override def writeStamp(): String = stamp.writeStamp()
@ -83,11 +83,11 @@ object FileCacheEntry {
case _ => None case _ => None
} }
override def equals(o: Any): Boolean = o match { override def equals(o: Any): Boolean = o match {
case DelegateFileCacheEntry(thatStamp) => this.stamp equiv thatStamp case DelegateFileAttributes(thatStamp) => this.stamp equiv thatStamp
case xStamp: XStamp => this.stamp equiv xStamp case xStamp: XStamp => this.stamp equiv xStamp
case _ => false case _ => false
} }
override def hashCode: Int = stamp.hashCode override def hashCode: Int = stamp.hashCode
override def toString: String = s"FileCacheEntry(hash = $hash, lastModified = $lastModified)" override def toString: String = s"FileAttributes(hash = $hash, lastModified = $lastModified)"
} }
} }

View File

@ -14,7 +14,7 @@ import java.util.concurrent.atomic.AtomicBoolean
import org.scalatest.{ FlatSpec, Matchers } import org.scalatest.{ FlatSpec, Matchers }
import sbt.Watched._ import sbt.Watched._
import sbt.WatchedSpec._ import sbt.WatchedSpec._
import sbt.internal.FileCacheEntry import sbt.internal.FileAttributes
import sbt.io._ import sbt.io._
import sbt.io.syntax._ import sbt.io.syntax._
import sbt.util.Logger import sbt.util.Logger
@ -26,16 +26,16 @@ class WatchedSpec extends FlatSpec with Matchers {
object Defaults { object Defaults {
def config( def config(
globs: Seq[Glob], globs: Seq[Glob],
fileEventMonitor: Option[FileEventMonitor[FileCacheEntry]] = None, fileEventMonitor: Option[FileEventMonitor[FileAttributes]] = None,
logger: Logger = NullLogger, logger: Logger = NullLogger,
handleInput: InputStream => Action = _ => Ignore, handleInput: InputStream => Action = _ => Ignore,
preWatch: (Int, Boolean) => Action = (_, _) => CancelWatch, preWatch: (Int, Boolean) => Action = (_, _) => CancelWatch,
onWatchEvent: FileCacheEntry.Event => Action = _ => Ignore, onWatchEvent: FileAttributes.Event => Action = _ => Ignore,
triggeredMessage: (Path, Int) => Option[String] = (_, _) => None, triggeredMessage: (Path, Int) => Option[String] = (_, _) => None,
watchingMessage: Int => Option[String] = _ => None watchingMessage: Int => Option[String] = _ => None
): WatchConfig = { ): WatchConfig = {
val monitor = fileEventMonitor.getOrElse { val monitor = fileEventMonitor.getOrElse {
val fileTreeRepository = FileTreeRepository.default(FileCacheEntry.default) val fileTreeRepository = FileTreeRepository.default(FileAttributes.default)
globs.foreach(fileTreeRepository.register) globs.foreach(fileTreeRepository.register)
FileEventMonitor.antiEntropy( FileEventMonitor.antiEntropy(
fileTreeRepository, fileTreeRepository,

View File

@ -101,7 +101,7 @@ object Keys {
val watchConfig = taskKey[WatchConfig]("The configuration for continuous execution.").withRank(BMinusSetting) val watchConfig = taskKey[WatchConfig]("The configuration for continuous execution.").withRank(BMinusSetting)
val watchLogger = taskKey[Logger]("A logger that reports watch events.").withRank(DSetting) val watchLogger = taskKey[Logger]("A logger that reports watch events.").withRank(DSetting)
val watchHandleInput = settingKey[InputStream => Watched.Action]("Function that is periodically invoked to determine if the continous build should be stopped or if a build should be triggered. It will usually read from stdin to respond to user commands.").withRank(BMinusSetting) val watchHandleInput = settingKey[InputStream => Watched.Action]("Function that is periodically invoked to determine if the continous build should be stopped or if a build should be triggered. It will usually read from stdin to respond to user commands.").withRank(BMinusSetting)
val watchOnEvent = taskKey[FileCacheEntry.Event => Watched.Action]("Determines how to handle a file event").withRank(BMinusSetting) val watchOnEvent = taskKey[FileAttributes.Event => Watched.Action]("Determines how to handle a file event").withRank(BMinusSetting)
val watchOnTermination = taskKey[(Watched.Action, String, State) => State]("Transforms the input state after the continuous build completes.").withRank(BMinusSetting) val watchOnTermination = taskKey[(Watched.Action, String, State) => State]("Transforms the input state after the continuous build completes.").withRank(BMinusSetting)
val watchService = settingKey[() => WatchService]("Service to use to monitor file system changes.").withRank(BMinusSetting) val watchService = settingKey[() => WatchService]("Service to use to monitor file system changes.").withRank(BMinusSetting)
val watchProjectSources = taskKey[Seq[Watched.WatchSource]]("Defines the sources for the sbt meta project to watch to trigger a reload.").withRank(CSetting) val watchProjectSources = taskKey[Seq[Watched.WatchSource]]("Defines the sources for the sbt meta project to watch to trigger a reload.").withRank(CSetting)
@ -472,7 +472,7 @@ object Keys {
@deprecated("No longer used", "1.3.0") @deprecated("No longer used", "1.3.0")
private[sbt] val executeProgress = settingKey[State => TaskProgress]("Experimental task execution listener.").withRank(DTask) private[sbt] val executeProgress = settingKey[State => TaskProgress]("Experimental task execution listener.").withRank(DTask)
private[sbt] val globalFileTreeRepository = AttributeKey[FileTreeRepository[FileCacheEntry]]( private[sbt] val globalFileTreeRepository = AttributeKey[FileTreeRepository[FileAttributes]](
"global-file-tree-repository", "global-file-tree-repository",
"Provides a view into the file system that may or may not cache the tree in memory", "Provides a view into the file system that may or may not cache the tree in memory",
1000 1000

View File

@ -22,7 +22,7 @@ import scala.collection.mutable
private[sbt] object ExternalHooks { private[sbt] object ExternalHooks {
private val javaHome = Option(System.getProperty("java.home")).map(Paths.get(_)) private val javaHome = Option(System.getProperty("java.home")).map(Paths.get(_))
def apply(options: CompileOptions, repo: FileTree.Repository): DefaultExternalHooks = { def apply(options: CompileOptions, repo: FileTree.Repository): DefaultExternalHooks = {
def listEntries(glob: Glob): Seq[Entry[FileCacheEntry]] = repo.get(glob) def listEntries(glob: Glob): Seq[Entry[FileAttributes]] = repo.get(glob)
import scala.collection.JavaConverters._ import scala.collection.JavaConverters._
val sources = options.sources() val sources = options.sources()
val cachedSources = new java.util.HashMap[File, Stamp] val cachedSources = new java.util.HashMap[File, Stamp]

View File

@ -27,7 +27,7 @@ private[sbt] object FileManagement {
private[sbt] def defaultFileTreeRepository( private[sbt] def defaultFileTreeRepository(
state: State, state: State,
extracted: Extracted extracted: Extracted
): FileTreeRepository[FileCacheEntry] = { ): FileTreeRepository[FileAttributes] = {
val pollingGlobs = extracted.getOpt(Keys.pollingGlobs).getOrElse(Nil) val pollingGlobs = extracted.getOpt(Keys.pollingGlobs).getOrElse(Nil)
val remaining = state.remainingCommands.map(_.commandLine) val remaining = state.remainingCommands.map(_.commandLine)
// If the session is interactive or if the commands include a continuous build, then use // If the session is interactive or if the commands include a continuous build, then use
@ -47,38 +47,38 @@ private[sbt] object FileManagement {
case _ => new WatchLogger { override def debug(msg: => Any): Unit = {} } case _ => new WatchLogger { override def debug(msg: => Any): Unit = {} }
} }
if (enableCache) { if (enableCache) {
if (pollingGlobs.isEmpty) FileTreeRepository.default(FileCacheEntry.default) if (pollingGlobs.isEmpty) FileTreeRepository.default(FileAttributes.default)
else else
new HybridMonitoringRepository[FileCacheEntry]( new HybridMonitoringRepository[FileAttributes](
FileTreeRepository.hybrid(FileCacheEntry.default, pollingGlobs: _*), FileTreeRepository.hybrid(FileAttributes.default, pollingGlobs: _*),
pollInterval, pollInterval,
watchLogger watchLogger
) )
} else { } else {
if (Util.isWindows) new PollingFileRepository(FileCacheEntry.default) if (Util.isWindows) new PollingFileRepository(FileAttributes.default)
else { else {
val service = Watched.createWatchService(pollInterval) val service = Watched.createWatchService(pollInterval)
FileTreeRepository.legacy(FileCacheEntry.default _, (_: Any) => {}, service) FileTreeRepository.legacy(FileAttributes.default _, (_: Any) => {}, service)
} }
} }
} }
private[sbt] def monitor( private[sbt] def monitor(
repository: FileTreeRepository[FileCacheEntry], repository: FileTreeRepository[FileAttributes],
antiEntropy: FiniteDuration, antiEntropy: FiniteDuration,
logger: Logger logger: Logger
): FileEventMonitor[FileCacheEntry] = { ): FileEventMonitor[FileAttributes] = {
// Forwards callbacks to the repository. The close method removes all of these // Forwards callbacks to the repository. The close method removes all of these
// callbacks. // callbacks.
val copied: Observable[FileCacheEntry] = new Observable[FileCacheEntry] { val copied: Observable[FileAttributes] = new Observable[FileAttributes] {
private[this] val observers = new Observers[FileCacheEntry] private[this] val observers = new Observers[FileAttributes]
val underlying = repository match { val underlying = repository match {
case h: HybridPollingFileTreeRepository[FileCacheEntry] => case h: HybridPollingFileTreeRepository[FileAttributes] =>
h.toPollingRepository(antiEntropy, (msg: Any) => logger.debug(msg.toString)) h.toPollingRepository(antiEntropy, (msg: Any) => logger.debug(msg.toString))
case r => r case r => r
} }
private[this] val handle = underlying.addObserver(observers) private[this] val handle = underlying.addObserver(observers)
override def addObserver(observer: Observer[FileCacheEntry]): Int = override def addObserver(observer: Observer[FileAttributes]): Int =
observers.addObserver(observer) observers.addObserver(observer)
override def removeObserver(handle: Int): Unit = observers.removeObserver(handle) override def removeObserver(handle: Int): Unit = observers.removeObserver(handle)
override def close(): Unit = { override def close(): Unit = {
@ -86,7 +86,7 @@ private[sbt] object FileManagement {
underlying.close() underlying.close()
} }
} }
new FileEventMonitor[FileCacheEntry] { new FileEventMonitor[FileAttributes] {
val monitor = val monitor =
FileEventMonitor.antiEntropy( FileEventMonitor.antiEntropy(
copied, copied,
@ -95,13 +95,13 @@ private[sbt] object FileManagement {
50.millis, 50.millis,
10.minutes 10.minutes
) )
override def poll(duration: Duration): Seq[FileEventMonitor.Event[FileCacheEntry]] = override def poll(duration: Duration): Seq[FileEventMonitor.Event[FileAttributes]] =
monitor.poll(duration) monitor.poll(duration)
override def close(): Unit = monitor.close() override def close(): Unit = monitor.close()
} }
} }
private[sbt] def repo: Def.Initialize[Task[FileTreeRepository[FileCacheEntry]]] = Def.task { private[sbt] def repo: Def.Initialize[Task[FileTreeRepository[FileAttributes]]] = Def.task {
lazy val msg = s"Tried to get FileTreeRepository for uninitialized state." lazy val msg = s"Tried to get FileTreeRepository for uninitialized state."
state.value.get(Keys.globalFileTreeRepository).getOrElse(throw new IllegalStateException(msg)) state.value.get(Keys.globalFileTreeRepository).getOrElse(throw new IllegalStateException(msg))
} }

View File

@ -17,7 +17,7 @@ import sbt.io._
import scala.language.experimental.macros import scala.language.experimental.macros
private[sbt] object FileTree { private[sbt] object FileTree {
private[sbt] trait Repository extends sbt.internal.Repository[Seq, Glob, Entry[FileCacheEntry]] private[sbt] trait Repository extends sbt.internal.Repository[Seq, Glob, Entry[FileAttributes]]
private[sbt] object Repository { private[sbt] object Repository {
/** /**
@ -28,26 +28,26 @@ private[sbt] object FileTree {
*/ */
implicit def default: FileTree.Repository = macro MacroDefaults.fileTreeRepository implicit def default: FileTree.Repository = macro MacroDefaults.fileTreeRepository
private[sbt] object polling extends Repository { private[sbt] object polling extends Repository {
val view = FileTreeView.DEFAULT.asDataView(FileCacheEntry.default) val view = FileTreeView.DEFAULT.asDataView(FileAttributes.default)
override def get(key: Glob): Seq[Entry[FileCacheEntry]] = view.listEntries(key) override def get(key: Glob): Seq[Entry[FileAttributes]] = view.listEntries(key)
override def close(): Unit = {} override def close(): Unit = {}
} }
} }
private class ViewRepository(underlying: FileTreeDataView[FileCacheEntry]) extends Repository { private class ViewRepository(underlying: FileTreeDataView[FileAttributes]) extends Repository {
override def get(key: Glob): Seq[Entry[FileCacheEntry]] = underlying.listEntries(key) override def get(key: Glob): Seq[Entry[FileAttributes]] = underlying.listEntries(key)
override def close(): Unit = {} override def close(): Unit = {}
} }
private class CachingRepository(underlying: FileTreeRepository[FileCacheEntry]) private class CachingRepository(underlying: FileTreeRepository[FileAttributes])
extends Repository { extends Repository {
override def get(key: Glob): Seq[Entry[FileCacheEntry]] = { override def get(key: Glob): Seq[Entry[FileAttributes]] = {
underlying.register(key) underlying.register(key)
underlying.listEntries(key) underlying.listEntries(key)
} }
override def close(): Unit = underlying.close() override def close(): Unit = underlying.close()
} }
private[sbt] def repository(underlying: FileTreeDataView[FileCacheEntry]): Repository = private[sbt] def repository(underlying: FileTreeDataView[FileAttributes]): Repository =
underlying match { underlying match {
case r: FileTreeRepository[FileCacheEntry] => new CachingRepository(r) case r: FileTreeRepository[FileAttributes] => new CachingRepository(r)
case v => new ViewRepository(v) case v => new ViewRepository(v)
} }
} }