diff options
Diffstat (limited to 'core/src/main/scala/forge/util/PathRef.scala')
-rw-r--r-- | core/src/main/scala/forge/util/PathRef.scala | 57 |
1 files changed, 57 insertions, 0 deletions
diff --git a/core/src/main/scala/forge/util/PathRef.scala b/core/src/main/scala/forge/util/PathRef.scala new file mode 100644 index 00000000..dbe1ebbd --- /dev/null +++ b/core/src/main/scala/forge/util/PathRef.scala @@ -0,0 +1,57 @@ +package forge +package util + +import java.io.IOException +import java.nio.file.{FileVisitResult, FileVisitor} +import java.nio.file.attribute.BasicFileAttributes +import java.security.MessageDigest +import java.nio.{file => jnio} +import play.api.libs.json.{Format, Json} + + +/** + * A wrapper around `ammonite.ops.Path` that calculates it's hashcode based + * on the contents of the filesystem underneath it. Used to ensure filesystem + * changes can bust caches which are keyed off hashcodes. + */ +case class PathRef(path: ammonite.ops.Path){ + val md5Hash = { + val digest = MessageDigest.getInstance("MD5") + + val buffer = new Array[Byte](16 * 1024) + jnio.Files.walkFileTree( + path.toNIO, + new FileVisitor[jnio.Path] { + def preVisitDirectory(dir: jnio.Path, attrs: BasicFileAttributes) = { + digest.update(dir.toAbsolutePath.toString.getBytes) + FileVisitResult.CONTINUE + } + + def visitFile(file: jnio.Path, attrs: BasicFileAttributes) = { + digest.update(file.toAbsolutePath.toString.getBytes) + val is = jnio.Files.newInputStream(file) + def rec(): Unit = { + val length = is.read(buffer) + if (length != -1){ + digest.update(buffer, 0, length) + rec() + } + } + rec() + FileVisitResult.CONTINUE + } + + def visitFileFailed(file: jnio.Path, exc: IOException) = FileVisitResult.CONTINUE + def postVisitDirectory(dir: jnio.Path, exc: IOException) = FileVisitResult.CONTINUE + } + ) + + java.util.Arrays.hashCode(digest.digest()) + + } + override def hashCode() = md5Hash +} + +object PathRef{ + implicit def jsonFormatter: Format[PathRef] = Json.format +} |