summaryrefslogtreecommitdiff
path: root/core/src/main/scala/forge/eval/PathRef.scala
diff options
context:
space:
mode:
Diffstat (limited to 'core/src/main/scala/forge/eval/PathRef.scala')
-rw-r--r--core/src/main/scala/forge/eval/PathRef.scala60
1 files changed, 60 insertions, 0 deletions
diff --git a/core/src/main/scala/forge/eval/PathRef.scala b/core/src/main/scala/forge/eval/PathRef.scala
new file mode 100644
index 00000000..1c9bc700
--- /dev/null
+++ b/core/src/main/scala/forge/eval/PathRef.scala
@@ -0,0 +1,60 @@
+package forge.eval
+
+import java.io.IOException
+import java.nio.file.attribute.BasicFileAttributes
+import java.nio.file.{FileVisitResult, FileVisitor}
+import java.nio.{file => jnio}
+import java.security.MessageDigest
+
+import ammonite.ops.Path
+import forge.util.JsonFormatters
+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{
+ private implicit val pathFormat: Format[Path] = JsonFormatters.pathFormat
+ implicit def jsonFormatter: Format[PathRef] = Json.format
+}