Cleanup FileInfo

This commit is contained in:
Dale Wijnand 2016-11-30 15:03:38 +00:00
parent d86eab7a7a
commit 875a30cc70
No known key found for this signature in database
GPG Key ID: 4F256E3D151DF5EF
1 changed files with 61 additions and 84 deletions

View File

@ -3,115 +3,101 @@
*/
package sbt.internal.util
import sbt.io.Hash
import java.io.File
import sjsonnew.{ Builder, deserializationError, JsonFormat, Unbuilder }
import sbt.io.Hash
import sjsonnew.{ Builder, JsonFormat, Unbuilder, deserializationError }
import CacheImplicits._
sealed trait FileInfo {
def file: File
}
sealed trait HashFileInfo extends FileInfo {
def hash: List[Byte]
}
sealed trait ModifiedFileInfo extends FileInfo {
def lastModified: Long
}
sealed trait PlainFileInfo extends FileInfo {
def exists: Boolean
}
sealed trait FileInfo { def file: File }
sealed trait HashFileInfo extends FileInfo { def hash: List[Byte] }
sealed trait ModifiedFileInfo extends FileInfo { def lastModified: Long }
sealed trait PlainFileInfo extends FileInfo { def exists: Boolean }
sealed trait HashModifiedFileInfo extends HashFileInfo with ModifiedFileInfo
private final case class PlainFile(file: File, exists: Boolean) extends PlainFileInfo
private final case class FileModified(file: File, lastModified: Long) extends ModifiedFileInfo
private final case class FileHash(file: File, hash: List[Byte]) extends HashFileInfo
private final case class FileHashModified(file: File, hash: List[Byte], lastModified: Long) extends HashModifiedFileInfo
object FileInfo {
final case class FilesInfo[F <: FileInfo] private (files: Set[F])
object FilesInfo {
implicit def format[F <: FileInfo]: JsonFormat[FilesInfo[F]] = implicitly
def empty[F <: FileInfo]: FilesInfo[F] = FilesInfo(Set.empty[F])
}
object FileInfo {
sealed trait Style {
type F <: FileInfo
implicit val format: JsonFormat[F]
def apply(file: File): F
def apply(files: Set[File]): FilesInfo[F] = FilesInfo(files map apply)
def unapply(info: F): File = info.file
def unapply(infos: FilesInfo[F]): Set[File] = infos.files map (_.file)
}
object full extends Style {
override type F = HashModifiedFileInfo
type F = HashModifiedFileInfo
override implicit val format: JsonFormat[HashModifiedFileInfo] = new JsonFormat[HashModifiedFileInfo] {
override def read[J](jsOpt: Option[J], unbuilder: Unbuilder[J]): HashModifiedFileInfo =
jsOpt match {
case Some(js) =>
unbuilder.beginObject(js)
val file = unbuilder.readField[File]("file")
val hash = unbuilder.readField[List[Byte]]("hash")
val lastModified = unbuilder.readField[Long]("lastModified")
unbuilder.endObject()
FileHashModified(file, hash, lastModified)
case None =>
deserializationError("Expected JsObject but found None")
}
override def write[J](obj: HashModifiedFileInfo, builder: Builder[J]): Unit = {
implicit val format: JsonFormat[HashModifiedFileInfo] = new JsonFormat[HashModifiedFileInfo] {
def write[J](obj: HashModifiedFileInfo, builder: Builder[J]) = {
builder.beginObject()
builder.addField("file", obj.file)
builder.addField("hash", obj.hash)
builder.addField("lastModified", obj.lastModified)
builder.endObject()
}
def read[J](jsOpt: Option[J], unbuilder: Unbuilder[J]) = jsOpt match {
case Some(js) =>
unbuilder.beginObject(js)
val file = unbuilder.readField[File]("file")
val hash = unbuilder.readField[List[Byte]]("hash")
val lastModified = unbuilder.readField[Long]("lastModified")
unbuilder.endObject()
FileHashModified(file, hash, lastModified)
case None => deserializationError("Expected JsObject but found None")
}
}
override implicit def apply(file: File): HashModifiedFileInfo =
implicit def apply(file: File): HashModifiedFileInfo =
FileHashModified(file.getAbsoluteFile, Hash(file).toList, file.lastModified)
}
object hash extends Style {
override type F = HashFileInfo
type F = HashFileInfo
override implicit val format: JsonFormat[HashFileInfo] = new JsonFormat[HashFileInfo] {
override def read[J](jsOpt: Option[J], unbuilder: Unbuilder[J]): HashFileInfo =
jsOpt match {
case Some(js) =>
unbuilder.beginObject(js)
val file = unbuilder.readField[File]("file")
val hash = unbuilder.readField[List[Byte]]("hash")
unbuilder.endObject()
FileHash(file, hash)
case None =>
deserializationError("Expected JsObject but found None")
}
override def write[J](obj: HashFileInfo, builder: Builder[J]): Unit = {
implicit val format: JsonFormat[HashFileInfo] = new JsonFormat[HashFileInfo] {
def write[J](obj: HashFileInfo, builder: Builder[J]) = {
builder.beginObject()
builder.addField("file", obj.file)
builder.addField("hash", obj.hash)
builder.endObject()
}
def read[J](jsOpt: Option[J], unbuilder: Unbuilder[J]) = jsOpt match {
case Some(js) =>
unbuilder.beginObject(js)
val file = unbuilder.readField[File]("file")
val hash = unbuilder.readField[List[Byte]]("hash")
unbuilder.endObject()
FileHash(file, hash)
case None => deserializationError("Expected JsObject but found None")
}
}
override implicit def apply(file: File): HashFileInfo =
FileHash(file.getAbsoluteFile, computeHash(file))
implicit def apply(file: File): HashFileInfo = FileHash(file.getAbsoluteFile, computeHash(file))
private def computeHash(file: File): List[Byte] =
try Hash(file).toList
catch { case _: Exception => Nil }
private def computeHash(file: File): List[Byte] = try Hash(file).toList catch { case _: Exception => Nil }
}
object lastModified extends Style {
override type F = ModifiedFileInfo
type F = ModifiedFileInfo
override implicit val format: JsonFormat[ModifiedFileInfo] = new JsonFormat[ModifiedFileInfo] {
implicit val format: JsonFormat[ModifiedFileInfo] = new JsonFormat[ModifiedFileInfo] {
override def read[J](jsOpt: Option[J], unbuilder: Unbuilder[J]): ModifiedFileInfo =
jsOpt match {
case Some(js) =>
@ -132,43 +118,34 @@ object FileInfo {
}
}
override implicit def apply(file: File): ModifiedFileInfo =
FileModified(file.getAbsoluteFile, file.lastModified)
implicit def apply(file: File): ModifiedFileInfo = FileModified(file.getAbsoluteFile, file.lastModified)
}
object exists extends Style {
override type F = PlainFileInfo
type F = PlainFileInfo
override implicit val format: JsonFormat[PlainFileInfo] = new JsonFormat[PlainFileInfo] {
override def read[J](jsOpt: Option[J], unbuilder: Unbuilder[J]): PlainFileInfo =
jsOpt match {
case Some(js) =>
unbuilder.beginObject(js)
val file = unbuilder.readField[File]("file")
val exists = unbuilder.readField[Boolean]("exists")
unbuilder.endObject()
PlainFile(file, exists)
case None =>
deserializationError("Expected JsObject but found None")
}
override def write[J](obj: PlainFileInfo, builder: Builder[J]): Unit = {
implicit val format: JsonFormat[PlainFileInfo] = new JsonFormat[PlainFileInfo] {
def write[J](obj: PlainFileInfo, builder: Builder[J]): Unit = {
builder.beginObject()
builder.addField("file", obj.file)
builder.addField("exists", obj.exists)
builder.endObject()
}
def read[J](jsOpt: Option[J], unbuilder: Unbuilder[J]) = jsOpt match {
case Some(js) =>
unbuilder.beginObject(js)
val file = unbuilder.readField[File]("file")
val exists = unbuilder.readField[Boolean]("exists")
unbuilder.endObject()
PlainFile(file, exists)
case None => deserializationError("Expected JsObject but found None")
}
}
override implicit def apply(file: File): PlainFileInfo = {
implicit def apply(file: File): PlainFileInfo = {
val abs = file.getAbsoluteFile
PlainFile(abs, abs.exists)
}
}
}
final case class FilesInfo[F <: FileInfo] private (files: Set[F])
object FilesInfo {
implicit def format[F <: FileInfo]: JsonFormat[FilesInfo[F]] = implicitly
def empty[F <: FileInfo]: FilesInfo[F] = FilesInfo(Set.empty[F])
}