Watching child dirs.
This commit is contained in:
parent
47947a90b9
commit
fecde624c1
@ -4,6 +4,7 @@ import com.jessebrault.ssg.buildscript.GroovyBuildScriptRunner
|
||||
import com.jessebrault.ssg.part.GspPartRenderer
|
||||
import com.jessebrault.ssg.part.PartFilePartsProvider
|
||||
import com.jessebrault.ssg.part.PartType
|
||||
import com.jessebrault.ssg.provider.WithWatchableDir
|
||||
import com.jessebrault.ssg.specialpage.GspSpecialPageRenderer
|
||||
import com.jessebrault.ssg.specialpage.SpecialPageFileSpecialPagesProvider
|
||||
import com.jessebrault.ssg.specialpage.SpecialPageType
|
||||
@ -14,6 +15,7 @@ import com.jessebrault.ssg.text.MarkdownFrontMatterGetter
|
||||
import com.jessebrault.ssg.text.MarkdownTextRenderer
|
||||
import com.jessebrault.ssg.text.TextFileTextsProvider
|
||||
import com.jessebrault.ssg.text.TextType
|
||||
import groovy.io.FileType
|
||||
import org.apache.logging.log4j.Level
|
||||
import org.apache.logging.log4j.LogManager
|
||||
import org.apache.logging.log4j.Logger
|
||||
@ -21,7 +23,11 @@ import org.apache.logging.log4j.core.LoggerContext
|
||||
import picocli.CommandLine
|
||||
|
||||
import java.nio.file.FileSystems
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Path
|
||||
import java.nio.file.StandardWatchEventKinds
|
||||
import java.nio.file.WatchEvent
|
||||
import java.nio.file.WatchKey
|
||||
import java.util.concurrent.Callable
|
||||
|
||||
@CommandLine.Command(
|
||||
@ -149,50 +155,62 @@ class StaticSiteGeneratorCli implements Callable<Integer> {
|
||||
private static Integer watch(Collection<Build> builds, StaticSiteGenerator ssg) {
|
||||
logger.traceEntry('builds: {}, ssg: {}', builds, ssg)
|
||||
|
||||
Collection<WatchableProvider> watchableProviders = []
|
||||
|
||||
builds.each {
|
||||
it.config.textProviders.each {
|
||||
if (it instanceof WatchableProvider) {
|
||||
watchableProviders << it
|
||||
}
|
||||
}
|
||||
it.config.templatesProviders.each {
|
||||
if (it instanceof WatchableProvider) {
|
||||
watchableProviders << it
|
||||
}
|
||||
}
|
||||
it.config.partsProviders.each {
|
||||
if (it instanceof WatchableProvider) {
|
||||
watchableProviders << it
|
||||
}
|
||||
}
|
||||
it.config.specialPagesProviders.each {
|
||||
if (it instanceof WatchableProvider) {
|
||||
watchableProviders << it
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Setup watchService and watchKeys
|
||||
def watchService = FileSystems.getDefault().newWatchService()
|
||||
Map<WatchKey, Path> watchKeys = [:]
|
||||
|
||||
watchableProviders.each {
|
||||
it.watchableDir.toPath().register(
|
||||
// Our Closure to register a path
|
||||
def registerPath = { Path path ->
|
||||
def watchKey = path.register(
|
||||
watchService,
|
||||
StandardWatchEventKinds.ENTRY_CREATE,
|
||||
StandardWatchEventKinds.ENTRY_DELETE,
|
||||
StandardWatchEventKinds.ENTRY_MODIFY
|
||||
)
|
||||
watchKeys[watchKey] = path
|
||||
}
|
||||
|
||||
// Get all base watchableDirs
|
||||
Collection<WithWatchableDir> watchableProviders = []
|
||||
builds.each {
|
||||
it.config.textProviders.each {
|
||||
if (it instanceof WithWatchableDir) {
|
||||
watchableProviders << it
|
||||
}
|
||||
}
|
||||
}
|
||||
// register them and their child directories using the Closure above
|
||||
watchableProviders.each {
|
||||
def baseDirFile = it.watchableDir
|
||||
registerPath(baseDirFile.toPath())
|
||||
baseDirFile.eachFile(FileType.DIRECTORIES) {
|
||||
registerPath(it.toPath())
|
||||
}
|
||||
}
|
||||
|
||||
//noinspection GroovyInfiniteLoopStatement
|
||||
while (true) {
|
||||
def watchKey = watchService.take()
|
||||
logger.debug('watchKey: {}', watchKey)
|
||||
watchKey.pollEvents().each {
|
||||
logger.debug('watchEvent: {}', it)
|
||||
def path = watchKeys[watchKey]
|
||||
if (path == null) {
|
||||
logger.warn('unexpected watchKey: {}', watchKey)
|
||||
} else {
|
||||
watchKey.pollEvents().each {
|
||||
assert it instanceof WatchEvent<Path>
|
||||
def childName = it.context()
|
||||
def childPath = path.resolve(childName)
|
||||
logger.debug('childName: {}, childPath: {}', childName, childPath)
|
||||
if (it.kind() == StandardWatchEventKinds.ENTRY_CREATE && Files.isDirectory(childPath)) {
|
||||
logger.debug('registering dir with path: {}', childPath)
|
||||
registerPath(childPath)
|
||||
}
|
||||
}
|
||||
}
|
||||
def valid = watchKey.reset()
|
||||
if (!valid) {
|
||||
def removedPath = watchKeys.remove(watchKey)
|
||||
logger.debug('removed path: {}', removedPath)
|
||||
}
|
||||
watchKey.reset()
|
||||
}
|
||||
|
||||
//noinspection GroovyUnreachableStatement
|
||||
|
@ -26,7 +26,7 @@ class SimpleStaticSiteGenerator implements StaticSiteGenerator {
|
||||
def config = build.config
|
||||
|
||||
// Get all texts, templates, parts, and specialPages
|
||||
def texts = config.textProviders.collectMany { it.getTextFiles() }
|
||||
def texts = config.textProviders.collectMany { it.provide() }
|
||||
def templates = config.templatesProviders.collectMany { it.getTemplates() }
|
||||
def parts = config.partsProviders.collectMany { it.getParts() }
|
||||
def specialPages = config.specialPagesProviders.collectMany { it.getSpecialPages() }
|
||||
|
@ -0,0 +1,5 @@
|
||||
package com.jessebrault.ssg.provider
|
||||
|
||||
interface Provider<T> {
|
||||
T provide()
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
package com.jessebrault.ssg.provider
|
||||
|
||||
trait WithWatchableDir {
|
||||
File watchableDir
|
||||
}
|
@ -1,8 +1,8 @@
|
||||
package com.jessebrault.ssg.text
|
||||
|
||||
import com.jessebrault.ssg.provider.WithWatchableDir
|
||||
import com.jessebrault.ssg.util.FileNameHandler
|
||||
import com.jessebrault.ssg.util.RelativePathHandler
|
||||
import com.jessebrault.ssg.WatchableProvider
|
||||
import groovy.io.FileType
|
||||
import groovy.transform.EqualsAndHashCode
|
||||
import groovy.transform.NullCheck
|
||||
@ -11,7 +11,7 @@ import org.slf4j.LoggerFactory
|
||||
|
||||
@NullCheck
|
||||
@EqualsAndHashCode(includeFields = true)
|
||||
class TextFileTextsProvider implements TextsProvider, WatchableProvider {
|
||||
class TextFileTextsProvider implements TextsProvider, WithWatchableDir {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(TextFileTextsProvider)
|
||||
|
||||
@ -21,6 +21,9 @@ class TextFileTextsProvider implements TextsProvider, WatchableProvider {
|
||||
TextFileTextsProvider(Collection<TextType> textTypes, File textsDir) {
|
||||
this.textTypes = textTypes
|
||||
this.textsDir = textsDir
|
||||
if (!this.textsDir.isDirectory()) {
|
||||
throw new IllegalArgumentException('textsDir must be a directory, given: ' + this.textsDir)
|
||||
}
|
||||
this.watchableDir = this.textsDir
|
||||
}
|
||||
|
||||
@ -31,11 +34,7 @@ class TextFileTextsProvider implements TextsProvider, WatchableProvider {
|
||||
}
|
||||
|
||||
@Override
|
||||
Collection<Text> getTextFiles() {
|
||||
if (!this.textsDir.isDirectory()) {
|
||||
throw new IllegalArgumentException('textsDir must be a directory')
|
||||
}
|
||||
|
||||
Collection<Text> provide() {
|
||||
def textFiles = []
|
||||
this.textsDir.eachFileRecurse(FileType.FILES) {
|
||||
def type = this.getTextType(it)
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.jessebrault.ssg.text
|
||||
|
||||
interface TextsProvider {
|
||||
Collection<Text> getTextFiles()
|
||||
import com.jessebrault.ssg.provider.Provider
|
||||
|
||||
interface TextsProvider extends Provider<Collection<Text>> {
|
||||
Collection<TextType> getTextTypes()
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ class TextFileTextsProviderTests {
|
||||
void findsFile() {
|
||||
new FileTreeBuilder(this.textsDir).file('test.md', '**Hello, World!**')
|
||||
|
||||
def r = this.textsProvider.getTextFiles()
|
||||
def r = this.textsProvider.provide()
|
||||
assertEquals(1, r.size())
|
||||
def f0 = r[0]
|
||||
assertEquals('test', f0.path)
|
||||
@ -36,7 +36,7 @@ class TextFileTextsProviderTests {
|
||||
file('nested.md', '**Hello!**')
|
||||
}
|
||||
|
||||
def r = this.textsProvider.getTextFiles()
|
||||
def r = this.textsProvider.provide()
|
||||
assertEquals(1, r.size())
|
||||
def f0 = r[0]
|
||||
assertEquals('nested/nested', f0.path)
|
||||
@ -48,7 +48,7 @@ class TextFileTextsProviderTests {
|
||||
void ignoresUnsupportedFile() {
|
||||
new FileTreeBuilder(this.textsDir).file('.ignored', 'Ignored!')
|
||||
|
||||
def r = this.textsProvider.getTextFiles()
|
||||
def r = this.textsProvider.provide()
|
||||
assertEquals(0, r.size())
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user