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