caseapp.core.app.ProfileFileUpdater.scala Maven / Gradle / Ivy
package caseapp.core.app
// from https://github.com/VirtusLab/scala-cli/blob/eced0b35c769eca58ae6f1b1a3be0f29a8700859/modules/cli/src/main/scala/scala/cli/internal/ProfileFileUpdater.scala
import java.nio.charset.Charset
import java.nio.file.{FileAlreadyExistsException, Files, Path}
// initially adapted from https://github.com/coursier/coursier/blob/d9a0fcc1af4876bec7f19a18f2c93d808e06df8d/modules/env/src/main/scala/coursier/env/ProfileUpdater.scala#L44-L137
object ProfileFileUpdater {
private def startEndIndices(start: String, end: String, content: String): Option[(Int, Int)] = {
val startIdx = content.indexOf(start)
if (startIdx >= 0) {
val endIdx = content.indexOf(end, startIdx + 1)
if (endIdx >= 0)
Some(startIdx, endIdx + end.length)
else
None
}
else
None
}
def addToProfileFile(
file: Path,
title: String,
addition: String,
charset: Charset
): Boolean = {
def updated(content: String): Option[String] = {
val start = s"# >>> $title >>>\n"
val endStr = s"# <<< $title <<<\n"
val withTags = "\n" +
start +
addition.stripSuffix("\n") + "\n" + endStr
if (content.contains(withTags))
None
else
Some {
startEndIndices(start, endStr, content) match {
case None =>
content + withTags
case Some((startIdx, endIdx)) =>
content.take(startIdx) +
withTags +
content.drop(endIdx)
}
}
}
var updatedSomething = false
val contentOpt = Some(file)
.filter(Files.exists(_))
.map(f => new String(Files.readAllBytes(f), charset))
for (updatedContent <- updated(contentOpt.getOrElse(""))) {
Option(file.getParent).map(createDirectories(_))
Files.write(file, updatedContent.getBytes(charset))
updatedSomething = true
}
updatedSomething
}
def removeFromProfileFile(
file: Path,
title: String,
charset: Charset
): Boolean = {
def updated(content: String): Option[String] = {
val start = s"# >>> $title >>>\n"
val end = s"# <<< $title <<<\n"
startEndIndices(start, end, content).map {
case (startIdx, endIdx) =>
content.take(startIdx).stripSuffix("\n") +
content.drop(endIdx)
}
}
var updatedSomething = false
val contentOpt = Some(file)
.filter(Files.exists(_))
.map(f => new String(Files.readAllBytes(f), charset))
for (updatedContent <- updated(contentOpt.getOrElse(""))) {
Option(file.getParent).map(createDirectories(_))
Files.write(file, updatedContent.getBytes(charset))
updatedSomething = true
}
updatedSomething
}
private def createDirectories(path: Path): Unit =
try Files.createDirectories(path)
catch {
// Ignored, see https://bugs.openjdk.java.net/browse/JDK-8130464
case _: FileAlreadyExistsException if Files.isDirectory(path) =>
}
}