Skip to content

Commit

Permalink
Fixes shyiko#2 : Overlapping Paths
Browse files Browse the repository at this point in the history
  • Loading branch information
thecoden committed Dec 7, 2020
1 parent 7a657ba commit c97eea7
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 7 deletions.
20 changes: 13 additions & 7 deletions src/main/java/com/github/shyiko/klob/internal/package.kt
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,14 @@ internal fun visit(dir: File, filter: FileFilter, directoryModeFilter: FileFilte
internal fun visit(path: Path, option: EnumSet<IterationOption>, patterns: List<String>): Sequence<Path> {
val includeChildren = !option.contains(IterationOption.SKIP_CHILDREN)
val directoryMode = option.contains(IterationOption.DIRECTORY)

if (includeChildren && directoryMode) {
throw UnsupportedOperationException(
"Glob.IterationOption.DIRECTORY must be used together with Glob.IterationOption.SKIP_CHILDREN " +
"(please create a ticket at https://github.com/shyiko/klob/issue if it doesn't fit your needs)"
)
}

val baseDir = path.toString()
val filter = GlobFileFilter(baseDir,
*patterns.toTypedArray(),
Expand All @@ -58,6 +60,7 @@ internal fun visit(path: Path, option: EnumSet<IterationOption>, patterns: List<
if (option.contains(IterationOption.SKIP_HIDDEN))
it.and(HiddenFileFilter(reverse = true)) else it
}

val directoryModeFilter = when {
option.contains(IterationOption.DIRECTORY) ->
GlobFileFilter(baseDir,
Expand All @@ -67,14 +70,17 @@ internal fun visit(path: Path, option: EnumSet<IterationOption>, patterns: List<
)
else -> null
}

return patterns
.asSequence()
.map { Glob.prefix(slash(it)) }
.distinct()
.map { (if (it.startsWith("/")) File(fromSlash(it)) else File(baseDir, fromSlash(it))).canonicalPath }
// remove overlapping paths (e.g. /a & /a/b -> /a)
.sorted()
.fold(ArrayList<String>(), { r, v -> if (r.isEmpty() || !v.startsWith(r.last())) { r.add(v) }; r })
.map { visit(File(it), filter, directoryModeFilter) }
.asSequence()
.flatten()
.map {
val file = if (it.startsWith("/"))
File(fromSlash(it))
else
File(baseDir, fromSlash(it))

visit(file, filter, directoryModeFilter)
}.flatten()
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package com.github.shyiko.klob.internal

import com.github.shyiko.klob.Glob
import org.testng.Assert.assertFalse
import org.testng.Assert.assertTrue
import org.testng.annotations.Test
import java.io.File
import java.nio.file.Path

class GlobFileFilterTest {

Expand All @@ -27,4 +29,31 @@ class GlobFileFilterTest {
.accept(File("/C:/ktlint/src/test/kotlin/com/github/shyiko/ktlint/LinterTest.kt")))
}

/**
* Test paths for which the directories are a substring of another, using the [GlobFileFilter] class directly.
*/
@Test
fun testSubPathFold_regression() {
val filter = GlobFileFilter(dir, "$dir/a/b/a-b.txt", "$dir/a/b1/a-b1.txt")

assertTrue(filter.accept(File("$dir/a/b/a-b.txt")))
assertTrue(filter.accept(File("$dir/a/b1/a-b1.txt")))
}

/**
* Test paths for which the directories are a substring of another, using the the [Glob] interface the way a user normally would.
*/
@Test
fun testSubPathFold_regressionFromFiles() {
val basePath = File("test-files").toPath().toAbsolutePath()
val files = Glob.from("a/b/a-b.txt", "a/b1/a-b1.txt", "a/b/c/a-b-c.txt").iterate(basePath, Glob.IterationOption.SKIP_HIDDEN).asSequence().toList().map {
it.toString().removePrefix(basePath.toString())
}.toHashSet()

assertTrue(files.contains("/a/b/a-b.txt"), "/a/b/a-b.txt not matched.\n$files")
assertTrue(files.contains("/a/b1/a-b1.txt"), "/a/b1/a-b1.txt not matched\n$files")
assertTrue(files.contains("/a/b/c/a-b-c.txt"), "/a/b/c/a-b-c.txt not matched\n$files")
assertTrue(3 == files.size, "Only 3 files should match instead of ${files.size}\n${files}")
}

}
Empty file added test-files/a/b/a-b.txt
Empty file.
Empty file added test-files/a/b/c/a-b-c.txt
Empty file.
Empty file added test-files/a/b1/a-b1.txt
Empty file.

0 comments on commit c97eea7

Please sign in to comment.