refactor(build): migrate to NIO

This commit is contained in:
Harsh Shandilya 2024-05-31 18:14:17 +05:30
parent 36b45f90f9
commit 0f7405a91a
4 changed files with 41 additions and 21 deletions

View file

@ -1,7 +1,16 @@
package app.passwordstore.gradle.crowdin
import java.io.File
import java.nio.file.Path
import javax.xml.parsers.DocumentBuilderFactory
import kotlin.io.path.ExperimentalPathApi
import kotlin.io.path.deleteIfExists
import kotlin.io.path.deleteRecursively
import kotlin.io.path.inputStream
import kotlin.io.path.isDirectory
import kotlin.io.path.listDirectoryEntries
import kotlin.io.path.name
import kotlin.io.path.pathString
import kotlin.io.path.walk
import org.gradle.api.DefaultTask
import org.gradle.api.GradleException
import org.gradle.api.file.DirectoryProperty
@ -10,6 +19,7 @@ import org.gradle.api.tasks.TaskAction
import org.gradle.work.DisableCachingByDefault
import org.w3c.dom.Document
@OptIn(ExperimentalPathApi::class)
@DisableCachingByDefault(because = "The task runs quickly and has complicated semantics")
abstract class StringCleanupTask : DefaultTask() {
@ -19,12 +29,12 @@ abstract class StringCleanupTask : DefaultTask() {
fun clean() {
val sourceSets = arrayOf("main", "nonFree")
for (sourceSet in sourceSets) {
val fileTreeWalk = sourceDirectory.dir("$sourceSet/res").get().asFile.walkTopDown()
val fileTreeWalk = sourceDirectory.dir("$sourceSet/res").get().asFile.toPath().walk()
val valuesDirectories =
fileTreeWalk.filter { it.isDirectory }.filter { it.name.startsWith("values") }
fileTreeWalk.filter { it.isDirectory() }.filter { it.name.startsWith("values") }
val stringFiles = fileTreeWalk.filter { it.name == "strings.xml" }
val sourceFile =
stringFiles.firstOrNull { it.path.endsWith("values/strings.xml") }
stringFiles.firstOrNull { it.pathString.endsWith("values/strings.xml") }
?: throw GradleException("No root strings.xml found in '$sourceSet' sourceSet")
val sourceDoc = parseDocument(sourceFile)
val baselineStringCount = countStrings(sourceDoc)
@ -34,22 +44,22 @@ abstract class StringCleanupTask : DefaultTask() {
val doc = parseDocument(file)
val stringCount = countStrings(doc)
if (stringCount < threshold) {
file.delete()
file.deleteIfExists()
}
}
}
valuesDirectories.forEach { dir ->
if (dir.listFiles().isNullOrEmpty()) {
dir.delete()
if (dir.listDirectoryEntries().isEmpty()) {
dir.deleteRecursively()
}
}
}
}
private fun parseDocument(file: File): Document {
private fun parseDocument(path: Path): Document {
val dbFactory = DocumentBuilderFactory.newInstance()
val documentBuilder = dbFactory.newDocumentBuilder()
return documentBuilder.parse(file)
return documentBuilder.parse(path.inputStream())
}
private fun countStrings(document: Document): Int {

View file

@ -2,7 +2,10 @@ package app.passwordstore.gradle.ktfmt
import app.passwordstore.gradle.KtfmtPlugin
import com.facebook.ktfmt.format.Formatter
import java.io.File
import java.nio.file.Path
import kotlin.io.path.pathString
import kotlin.io.path.readText
import kotlin.io.path.relativeTo
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.async
@ -35,7 +38,7 @@ abstract class KtfmtCheckTask : SourceTask() {
fun execute() {
runBlocking(Dispatchers.IO.limitedParallelism(PARALLEL_TASK_LIMIT)) {
coroutineScope {
val results = inputFiles.map { async { checkFile(it) } }.awaitAll()
val results = inputFiles.map { async { checkFile(it.toPath()) } }.awaitAll()
if (results.any { (notFormatted, _) -> notFormatted }) {
val prettyDiff =
results
@ -48,10 +51,12 @@ abstract class KtfmtCheckTask : SourceTask() {
}
}
private fun checkFile(input: File): Pair<Boolean, List<KtfmtDiffEntry>> {
private fun checkFile(input: Path): Pair<Boolean, List<KtfmtDiffEntry>> {
val originCode = input.readText()
val formattedCode = Formatter.format(KtfmtPlugin.DEFAULT_FORMATTING_OPTIONS, originCode)
val pathNormalizer = { file: File -> file.toRelativeString(projectDirectory.asFile.get()) }
val pathNormalizer = { file: Path ->
file.relativeTo(projectDirectory.asFile.get().toPath()).pathString
}
return (originCode != formattedCode) to
KtfmtDiffer.computeDiff(input, formattedCode, pathNormalizer)
}

View file

@ -4,13 +4,14 @@ import com.github.difflib.DiffUtils
import com.github.difflib.patch.ChangeDelta
import com.github.difflib.patch.DeleteDelta
import com.github.difflib.patch.InsertDelta
import java.io.File
import java.nio.file.Path
import kotlin.io.path.readText
object KtfmtDiffer {
fun computeDiff(
inputFile: File,
inputFile: Path,
formattedCode: String,
pathNormalizer: (File) -> String,
pathNormalizer: (Path) -> String,
): List<KtfmtDiffEntry> {
val originCode = inputFile.readText()
return DiffUtils.diff(originCode, formattedCode, null).deltas.map {

View file

@ -2,7 +2,11 @@ package app.passwordstore.gradle.ktfmt
import app.passwordstore.gradle.KtfmtPlugin
import com.facebook.ktfmt.format.Formatter
import java.io.File
import java.nio.file.Path
import kotlin.io.path.pathString
import kotlin.io.path.readText
import kotlin.io.path.relativeTo
import kotlin.io.path.writeText
import org.gradle.api.logging.LogLevel
import org.gradle.api.logging.Logger
import org.gradle.api.logging.Logging
@ -12,22 +16,22 @@ import org.gradle.workers.WorkAction
abstract class KtfmtWorkerAction : WorkAction<KtfmtWorkerParameters> {
private val logger: Logger =
DefaultContextAwareTaskLogger(Logging.getLogger(KtfmtFormatTask::class.java))
private val files: List<File> = parameters.files.toList()
private val projectDirectory: File = parameters.projectDirectory.asFile.get()
private val files: List<Path> = parameters.files.toList().map { it.toPath() }
private val projectDirectory: Path = parameters.projectDirectory.asFile.get().toPath()
private val name: String = parameters.name.get()
override fun execute() {
try {
files.forEach { file ->
val sourceText = file.readText()
val relativePath = file.toRelativeString(projectDirectory)
val relativePath = file.relativeTo(projectDirectory).pathString
logger.log(LogLevel.DEBUG, "$name checking format: $relativePath")
val formattedText = Formatter.format(KtfmtPlugin.DEFAULT_FORMATTING_OPTIONS, sourceText)
if (!formattedText.contentEquals(sourceText)) {
logger.log(LogLevel.QUIET, "${file.toRelativeString(projectDirectory)}: Format fixed")
logger.log(LogLevel.QUIET, "$relativePath: Format fixed")
file.writeText(formattedText)
}
}