1
0
Fork 0
mirror of https://github.com/ethauvin/kobalt.git synced 2025-04-27 00:38:11 -07:00
kobalt/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/FileSpec.kt
2016-03-28 19:12:19 -07:00

102 lines
3.9 KiB
Kotlin

package com.beust.kobalt
import com.beust.kobalt.misc.log
import java.io.File
import java.nio.file.*
import java.nio.file.attribute.BasicFileAttributes
/**
* Subclasses of IFileSpec can be turned into a list of files. There are two kings: FileSpec (a single file)
* and GlobSpec (a spec defined by a glob, e.g. ** slash *Test.class)
*/
sealed class IFileSpec {
abstract fun toFiles(baseDir: String?, filePath: String, excludes: List<Glob> = emptyList<Glob>()): List<File>
class FileSpec(val spec: String) : IFileSpec() {
override fun toFiles(baseDir: String?, filePath: String, excludes: List<Glob>) = listOf(File(spec))
override fun toString() = spec
}
/**
* A glob matcher, see http://docs.oracle.com/javase/7/docs/api/java/nio/file/FileSystem.html#getPathMatcher%28java.lang.String%29
*/
class GlobSpec(val spec: List<String>) : IFileSpec() {
constructor(spec: String) : this(arrayListOf(spec))
private fun isIncluded(includeMatchers: Glob, excludes: List<Glob>, rel: Path) : Boolean {
excludes.forEach {
if (it.matches(rel)) {
log(3, "Excluding ${rel.toFile()}")
return false
}
}
if (includeMatchers.matches(rel)) {
log(3, "Including ${rel.toFile().path}")
return true
}
log(2, "Excluding ${rel.toFile()} (not matching any include pattern")
return false
}
override fun toFiles(baseDir: String?, filePath: String, excludes: List<Glob>): List<File> {
val result = arrayListOf<File>()
val includes = Glob(*spec.toTypedArray())
if (File(baseDir, filePath).isDirectory) {
val orgRootDir = (if (File(filePath).isAbsolute) Paths.get(filePath)
else if (baseDir != null) Paths.get(baseDir, filePath)
else Paths.get(filePath)).run { normalize() }
// Paths.get(".").normalize() returns an empty string, which is not a valid file :-(
val rootDir = if (orgRootDir.toFile().path.isEmpty()) Paths.get("./") else orgRootDir
if (rootDir.toFile().exists()) {
Files.walkFileTree(rootDir, object : SimpleFileVisitor<Path>() {
override fun visitFile(p: Path, attrs: BasicFileAttributes): FileVisitResult {
val path = p.normalize()
val rel = orgRootDir.relativize(path)
if (isIncluded(includes, excludes, path)) {
log(3, " including file " + rel.toFile() + " from rootDir $rootDir")
result.add(rel.toFile())
}
return FileVisitResult.CONTINUE
}
})
} else {
throw AssertionError("Directory \"$rootDir\" should exist")
}
} else {
if (isIncluded(includes, excludes, Paths.get(filePath))) {
result.add(File(filePath))
}
}
return result
}
override fun toString(): String {
var result = ""
spec.apply {
if (!isEmpty()) {
result += "Included files: " + joinToString { ", " }
}
}
return result
}
}
}
/**
* A Glob is a simple file name matcher.
*/
class Glob(vararg specs: String) {
val matchers = prepareMatchers(specs.toList())
private fun prepareMatchers(specs: List<String>): List<PathMatcher> =
specs.map { it -> FileSystems.getDefault().getPathMatcher("glob:$it") }
fun matches(s: String) = matches(Paths.get(s))
fun matches(path: Path) = matchers.any { it.matches(path) }
}