All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.scalajs.jsenv.VirtualFileMaterializer.scala Maven / Gradle / Ivy

package org.scalajs.jsenv

import scala.annotation.tailrec

import org.scalajs.core.tools.io._

import java.io.File

/** A helper class to temporarily store virtual files to the filesystem.
 *
 *  Can be used with tools that require real files.
 *  @param singleDir if true, forces files to be copied into
 *      [[cacheDir]]. Useful to setup include directories for
 *      example.
 */
final class VirtualFileMaterializer(singleDir: Boolean = false) {
  import VirtualFileMaterializer._

  val cacheDir = {
    val dir = createTempDir()
    dir.deleteOnExit()
    dir
  }

  /** Create a target file to write/copy to. Will also call
   *  deleteOnExit on the file.
   */
  private def trgFile(name: String): File = {
    val f = new File(cacheDir, name)
    f.deleteOnExit()
    f
  }

  def materialize(vf: VirtualTextFile): File = vf match {
    case vf: FileVirtualFile if !singleDir =>
      vf.file
    case _ =>
      val trg = trgFile(vf.name)
      IO.copyTo(vf, WritableFileVirtualTextFile(trg))
      trg
  }

  def materialize(vf: VirtualBinaryFile): File = vf match {
    case vf: FileVirtualFile if !singleDir =>
      vf.file
    case _ =>
      val trg = trgFile(vf.name)
      IO.copyTo(vf, WritableFileVirtualBinaryFile(trg))
      trg
  }

  /** Removes the cache directory. Any operation on this
   *  VirtualFileMaterializer is invalid after [[close]] has been
   *  called.
   */
  def close(): Unit = {
    cacheDir.listFiles().foreach(_.delete)
    cacheDir.delete()
  }

  // scalastyle:off line.size.limit
  /* Taken from Guava:
   * https://github.com/google/guava/blob/1c285fc8d289c43b46aa55e7f90ec0359be5b69a/guava/src/com/google/common/io/Files.java#L413-L426
   */
  // scalastyle:on line.size.limit
  private def createTempDir(): File = {
    val baseDir = new File(System.getProperty("java.io.tmpdir"))
    val baseName = System.currentTimeMillis() + "-"

    @tailrec
    def loop(tries: Int): File = {
      val tempDir = new File(baseDir, baseName + tries)
      if (tempDir.mkdir())
        tempDir
      else if (tries < TempDirAttempts)
        loop(tries + 1)
      else {
        throw new IllegalStateException("Failed to create directory within " +
            s"$TempDirAttempts attempts (tried ${baseName}0 to " +
            s"${baseName}${TempDirAttempts - 1})")
      }
    }

    loop(0)
  }

}

private object VirtualFileMaterializer {
  private final val TempDirAttempts = 10000
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy