gmethvin / directory-watcher

A cross-platform Java recursive directory watcher, with a JNA macOS watcher and Scala better-files integration
Apache License 2.0
265 stars 34 forks source link

The watcher stops watching recursive directories #1

Closed akkie closed 6 years ago

akkie commented 6 years ago

I've some issues using the library on Windows 7. I don't know if other Systems are also affected.

The problem is that the watcher stops watching after the following scenario:

In my case the watcher stops watching at this point. I can now create new files or delete existing ones. The watcher will report nothing.

The issue occurs with the following watcher code:

import io.methvin.watcher.DirectoryChangeEvent.EventType._
import io.methvin.watcher.DirectoryWatcher
val watcher = DirectoryWatcher.create(directory.path, { event =>
  event.eventType() match {
    case CREATE   => logger.info(s"${event.path()} got created")
    case MODIFY   => logger.info(s"${event.path()} got modified")
    case DELETE   => logger.info(s"${event.path()} got deleted")
    case OVERFLOW => logger.info(s"${event.path()} got overflow")
  }
})

watcher.watchAsync(context.system.dispatcher)

This is my output:

[info] a.FileImportService - C:\Users\...\files\import\Neuer Ordner got created
[info] a.FileImportService - C:\Users\...\files\import\Neuer Ordner got deleted
[info] a.FileImportService - C:\Users\...\files\import\test1 got created
[info] a.FileImportService - C:\Users\...\files\import\test1\Neuer Ordner got created
[info] a.FileImportService - C:\Users\...\files\import\test1 got modified
[info] a.FileImportService - C:\Users\...\files\import\test1\Neuer Ordner got deleted
[info] a.FileImportService - C:\Users\...\files\import\test1\test2 got created
[info] a.FileImportService - C:\Users\...\files\import\test1\test2\Neuer Ordner got created
[info] a.FileImportService - C:\Users\...\files\import\test1\test2 got modified
[info] a.FileImportService - C:\Users\...\files\import\test1\test2\Neuer Ordner got deleted
[info] a.FileImportService - C:\Users\...\files\import\test1\test2\test3 got created

I do not think it's a windows specific issue, because if I test this with the file monitor from better-files, then I cannot reproduce this issue.

gmethvin commented 6 years ago

@akkie which version is this on? I fixed a bug in version 0.1.4 which might be related to this. Also, my suspicion is that some exception is getting thrown that breaks it, so if you can wrap your watch() call in a try-catch you might be able to figure out what is.

gmethvin commented 6 years ago

I noticed that better-files has an onException method which by default does nothing, so you may be seeing a difference because better-files ignores the exception. I decided to do something similar and added an onException to the listener.

Can you try with 0.2.0? If you change your log level to DEBUG it will actually log the exception if there is one.

akkie commented 6 years ago

I've tried 0.2.0, but the issues remains. I've also tried to use the blocking version and wrap it in an exception blog. No exception will be thrown.

Today, I couldn't reproduce the issue with the steps posted from yesterday. But with other steps. It seems that the issue occurs sporadically.

[debug] i.m.w.DirectoryWatcher - ENTRY_CREATE [C:\Users\...\files\import\Neuer Ordner]
[debug] i.m.w.DirectoryWatcher - Registering [C:\Users\...\files\import\Neuer Ordner].
[info] a.FileImportService - C:\Users\...\files\import\Neuer Ordner got created
[debug] i.m.w.DirectoryWatcher - ENTRY_DELETE [C:\Users\...\files\import\Neuer Ordner]
[info] a.FileImportService - C:\Users\...\files\import\Neuer Ordner got deleted
[debug] i.m.w.DirectoryWatcher - ENTRY_CREATE [C:\Users\...\files\import\test1]
[debug] i.m.w.DirectoryWatcher - Registering [C:\Users\...\files\import\test1].
[info] a.FileImportService - C:\Users\...\files\import\test1 got created
[debug] i.m.w.DirectoryWatcher - ENTRY_CREATE [C:\Users\...\files\import\test1\Neuer Ordner]
[debug] i.m.w.DirectoryWatcher - Registering [C:\Users\...\files\import\test1\Neuer Ordner].
[info] a.FileImportService - C:\Users\...\files\import\test1\Neuer Ordner got created
[debug] i.m.w.DirectoryWatcher - ENTRY_MODIFY [C:\Users\...\files\import\test1]
[info] a.FileImportService - C:\Users\...\files\import\test1 got modified
[debug] i.m.w.DirectoryWatcher - ENTRY_DELETE [C:\Users\...\files\import\test1\Neuer Ordner]
[info] a.FileImportService - C:\Users\...\files\import\test1\Neuer Ordner got deleted
[debug] i.m.w.DirectoryWatcher - ENTRY_CREATE [C:\Users\...\files\import\test1\test2]
[debug] i.m.w.DirectoryWatcher - Registering [C:\Users\...\files\import\test1\test2].
[info] a.FileImportService - C:\Users\...\files\import\test1\test2 got created
[debug] i.m.w.DirectoryWatcher - ENTRY_MODIFY [C:\Users\...\files\import\test1]
[debug] i.m.w.DirectoryWatcher - Failed to hash modified file [C:\Users\...\files\import\test1]. It may have been deleted.
[debug] i.m.w.DirectoryWatcher - ENTRY_CREATE [C:\Users\...\files\import\test1\test2\Neuer Ordner]
[debug] i.m.w.DirectoryWatcher - Registering [C:\Users\...\files\import\test1\test2\Neuer Ordner].
[info] a.FileImportService - C:\Users\...\files\import\test1\test2\Neuer Ordner got created
[debug] i.m.w.DirectoryWatcher - ENTRY_MODIFY [C:\Users\...\files\import\test1\test2]
[info] a.FileImportService - C:\Users\...\files\import\test1\test2 got modified
[debug] i.m.w.DirectoryWatcher - ENTRY_DELETE [C:\Users\...\files\import\test1\test2\Neuer Ordner]
[info] a.FileImportService - C:\Users\...\files\import\test1\test2\Neuer Ordner got deleted
[debug] i.m.w.DirectoryWatcher - ENTRY_CREATE [C:\Users\...\files\import\test1\test2\test3]
[debug] i.m.w.DirectoryWatcher - Registering [C:\Users\...\files\import\test1\test2\test3].
[info] a.FileImportService - C:\Users\...\files\import\test1\test2\test3 got created
[debug] i.m.w.DirectoryWatcher - ENTRY_MODIFY [C:\Users\...\files\import\test1\test2]
[debug] i.m.w.DirectoryWatcher - Failed to hash modified file [C:\Users\...\files\import\test1\test2]. It may have been deleted.
[debug] i.m.w.DirectoryWatcher - ENTRY_CREATE [C:\Users\...\files\import\test1\test2\test3\Neues Textdokument.txt]
[info] a.FileImportService - C:\Users\...\files\import\test1\test2\test3\Neues Textdokument.txt got created
[debug] i.m.w.DirectoryWatcher - ENTRY_MODIFY [C:\Users\...\files\import\test1\test2\test3]
[info] a.FileImportService - C:\Users\...\files\import\test1\test2\test3 got modified
[debug] i.m.w.DirectoryWatcher - ENTRY_CREATE [C:\Users\...\files\import\Neues Textdokument.txt]
[info] a.FileImportService - C:\Users\...\files\import\Neues Textdokument.txt got created
[debug] i.m.w.DirectoryWatcher - ENTRY_DELETE [C:\Users\...\files\import\Neues Textdokument.txt]
[info] a.FileImportService - C:\Users\...\files\import\Neues Textdokument.txt got deleted
[debug] i.m.w.DirectoryWatcher - ENTRY_CREATE [C:\Users\...\files\import\Neues Textdokument.txt]
[info] a.FileImportService - C:\Users\...\files\import\Neues Textdokument.txt got created
[debug] i.m.w.DirectoryWatcher - ENTRY_CREATE [C:\Users\...\files\import\test1\test2\test3\Neues Textdokument (2).txt]
[info] a.FileImportService - C:\Users\...\files\import\test1\test2\test3\Neues Textdokument (2).txt got created
[debug] i.m.w.DirectoryWatcher - ENTRY_MODIFY [C:\Users\...\files\import\test1\test2\test3]
[debug] i.m.w.DirectoryWatcher - Failed to hash modified file [C:\Users\...\files\import\test1\test2\test3]. It may have been deleted.
[debug] i.m.w.DirectoryWatcher - ENTRY_CREATE [C:\Users\...\files\import\Neues Textdokument (2).txt]
[debug] i.m.w.DirectoryWatcher - Failed to hash created file [C:\Users\...\files\import\Neues Textdokument (2).txt]. It may have been deleted. [info] a.FileImportService - C:\Users\...\files\import\Neues Textdokument (2).txt got created
[debug] i.m.w.DirectoryWatcher - ENTRY_CREATE [C:\Users\...\files\import\test1\Neues Textdokument.txt]
[info] a.FileImportService - C:\Users\...\files\import\test1\Neues Textdokument.txt got created
[debug] i.m.w.DirectoryWatcher - ENTRY_MODIFY [C:\Users\...\files\import\test1]
[debug] i.m.w.DirectoryWatcher - Failed to hash modified file [C:\Users\...\files\import\test1]. It may have been deleted.
[debug] i.m.w.DirectoryWatcher - ENTRY_CREATE [C:\Users\...\files\import\test1\Neues Textdokument (2).txt]
[info] a.FileImportService - C:\Users\...\files\import\test1\Neues Textdokument (2).txt got created
[debug] i.m.w.DirectoryWatcher - ENTRY_MODIFY [C:\Users\...\files\import\test1]
[debug] i.m.w.DirectoryWatcher - Failed to hash modified file [C:\Users\...\files\import\test1]. It may have been deleted.
[debug] i.m.w.DirectoryWatcher - ENTRY_CREATE [C:\Users\...\files\import\test1\test2\Neues Textdokument.txt]
[info] a.FileImportService - C:\Users\...\files\import\test1\test2\Neues Textdokument.txt got created
[debug] i.m.w.DirectoryWatcher - ENTRY_MODIFY [C:\Users\...\files\import\test1\test2]
[debug] i.m.w.DirectoryWatcher - Failed to hash modified file [C:\Users\...\files\import\test1\test2]. It may have been deleted.
[debug] i.m.w.DirectoryWatcher - ENTRY_CREATE [C:\Users\...\files\import\test1\test2\test3\Neues Textdokument (3).txt]
[info] a.FileImportService - C:\Users\...\files\import\test1\test2\test3\Neues Textdokument (3).txt got created
[debug] i.m.w.DirectoryWatcher - ENTRY_MODIFY [C:\Users\...\files\import\test1\test2\test3]
[debug] i.m.w.DirectoryWatcher - Failed to hash modified file [C:\Users\...\files\import\test1\test2\test3]. It may have been deleted.
[debug] i.m.w.DirectoryWatcher - ENTRY_CREATE [C:\Users\...\files\import\test1\test2\Neues Textdokument (2).txt]
[info] a.FileImportService - C:\Users\...\files\import\test1\test2\Neues Textdokument (2).txt got created
[debug] i.m.w.DirectoryWatcher - ENTRY_MODIFY [C:\Users\...\files\import\test1\test2]
[debug] i.m.w.DirectoryWatcher - Failed to hash modified file [C:\Users\...\files\import\test1\test2]. It may have been deleted.
[debug] i.m.w.DirectoryWatcher - ENTRY_CREATE [C:\Users\...\files\import\Neuer Ordner]
[debug] i.m.w.DirectoryWatcher - Registering [C:\Users\...\files\import\Neuer Ordner].
[info] a.FileImportService - C:\Users\...\files\import\Neuer Ordner got created
[debug] i.m.w.DirectoryWatcher - ENTRY_CREATE [C:\Users\...\files\import\Neuer Ordner (2)]
[debug] i.m.w.DirectoryWatcher - Registering [C:\Users\...\files\import\Neuer Ordner (2)].
[info] a.FileImportService - C:\Users\...\files\import\Neuer Ordner (2) got created

After the last log the watcher stops watching.

akkie commented 6 years ago

Or another try:

[debug] i.m.w.DirectoryWatcher - ENTRY_CREATE [C:\Users\...\files\import\Neuer Ordner]
[debug] i.m.w.DirectoryWatcher - Registering [C:\Users\...\files\import\Neuer Ordner].
[info] a.FileImportService - C:\Users\...\files\import\Neuer Ordner got created
[debug] i.m.w.DirectoryWatcher - ENTRY_DELETE [C:\Users\...\files\import\Neuer Ordner]
[info] a.FileImportService - C:\Users\...\files\import\Neuer Ordner got deleted
[debug] i.m.w.DirectoryWatcher - ENTRY_CREATE [C:\Users\...\files\import\test]
[debug] i.m.w.DirectoryWatcher - Registering [C:\Users\...\files\import\test].
[info] a.FileImportService - C:\Users\...\files\import\test got created
[debug] i.m.w.DirectoryWatcher - ENTRY_CREATE [C:\Users\...\files\import\test\Neuer Ordner]
[debug] i.m.w.DirectoryWatcher - Registering [C:\Users\...\files\import\test\Neuer Ordner].
[info] a.FileImportService - C:\Users\...\files\import\test\Neuer Ordner got created
[debug] i.m.w.DirectoryWatcher - ENTRY_MODIFY [C:\Users\...\files\import\test]
[info] a.FileImportService - C:\Users\...\files\import\test got modified
[debug] i.m.w.DirectoryWatcher - ENTRY_DELETE [C:\Users\...\files\import\test\Neuer Ordner]
[info] a.FileImportService - C:\Users\...\files\import\test\Neuer Ordner got deleted
[debug] i.m.w.DirectoryWatcher - ENTRY_CREATE [C:\Users\...\files\import\test\test1]
[debug] i.m.w.DirectoryWatcher - Registering [C:\Users\...\files\import\test\test1].
[info] a.FileImportService - C:\Users\...\files\import\test\test1 got created
[debug] i.m.w.DirectoryWatcher - ENTRY_MODIFY [C:\Users\...\files\import\test]
[debug] i.m.w.DirectoryWatcher - Failed to hash modified file [C:\Users\...\files\import\test]. It may have been deleted.
[debug] i.m.w.DirectoryWatcher - ENTRY_CREATE [C:\Users\...\files\import\test\test1\Neuer Ordner]
[debug] i.m.w.DirectoryWatcher - Registering [C:\Users\...\files\import\test\test1\Neuer Ordner].
[info] a.FileImportService - C:\Users\...\files\import\test\test1\Neuer Ordner got created
[debug] i.m.w.DirectoryWatcher - ENTRY_MODIFY [C:\Users\...\files\import\test\test1]
[info] a.FileImportService - C:\Users\...\files\import\test\test1 got modified
[debug] i.m.w.DirectoryWatcher - ENTRY_DELETE [C:\Users\...\files\import\test\test1\Neuer Ordner]
[info] a.FileImportService - C:\Users\...\files\import\test\test1\Neuer Ordner got deleted
[debug] i.m.w.DirectoryWatcher - ENTRY_CREATE [C:\Users\...\files\import\test\test1\test2]
[debug] i.m.w.DirectoryWatcher - Registering [C:\Users\...\files\import\test\test1\test2].
[info] a.FileImportService - C:\Users\...\files\import\test\test1\test2 got created
[debug] i.m.w.DirectoryWatcher - ENTRY_MODIFY [C:\Users\...\files\import\test\test1]
[debug] i.m.w.DirectoryWatcher - Failed to hash modified file [C:\Users\...\files\import\test\test1]. It may have been deleted.
[debug] i.m.w.DirectoryWatcher - ENTRY_CREATE [C:\Users\...\files\import\test\test1\test2\Neuer Ordner]
[debug] i.m.w.DirectoryWatcher - Registering [C:\Users\...\files\import\test\test1\test2\Neuer Ordner].
[info] a.FileImportService - C:\Users\...\files\import\test\test1\test2\Neuer Ordner got created
[debug] i.m.w.DirectoryWatcher - ENTRY_MODIFY [C:\Users\...\files\import\test\test1\test2]
[info] a.FileImportService - C:\Users\...\files\import\test\test1\test2 got modified
[debug] i.m.w.DirectoryWatcher - ENTRY_DELETE [C:\Users\...\files\import\test\test1\test2\Neuer Ordner]
[info] a.FileImportService - C:\Users\...\files\import\test\test1\test2\Neuer Ordner got deleted
[debug] i.m.w.DirectoryWatcher - ENTRY_CREATE [C:\Users\...\files\import\test\test1\test2\test3]
[debug] i.m.w.DirectoryWatcher - Registering [C:\Users\...\files\import\test\test1\test2\test3].
[info] a.FileImportService - C:\Users\...\files\import\test\test1\test2\test3 got created
[debug] i.m.w.DirectoryWatcher - ENTRY_MODIFY [C:\Users\...\files\import\test\test1\test2]
[debug] i.m.w.DirectoryWatcher - Failed to hash modified file [C:\Users\...\files\import\test\test1\test2]. It may have been deleted.
[debug] i.m.w.DirectoryWatcher - ENTRY_CREATE [C:\Users\...\files\import\test\test1\test2\test3\Neuer Ordner]
[debug] i.m.w.DirectoryWatcher - Registering [C:\Users\...\files\import\test\test1\test2\test3\Neuer Ordner].
[info] a.FileImportService - C:\Users\...\files\import\test\test1\test2\test3\Neuer Ordner got created
[debug] i.m.w.DirectoryWatcher - ENTRY_MODIFY [C:\Users\...\files\import\test\test1\test2\test3]
[info] a.FileImportService - C:\Users\...\files\import\test\test1\test2\test3 got modified
[debug] i.m.w.DirectoryWatcher - ENTRY_DELETE [C:\Users\...\files\import\test\test1\test2\test3\Neuer Ordner]
[info] a.FileImportService - C:\Users\...\files\import\test\test1\test2\test3\Neuer Ordner got deleted
[debug] i.m.w.DirectoryWatcher - ENTRY_CREATE [C:\Users\...\files\import\test\test1\test2\test3\test4]
[debug] i.m.w.DirectoryWatcher - Registering [C:\Users\...\files\import\test\test1\test2\test3\test4].
[info] a.FileImportService - C:\Users\...\files\import\test\test1\test2\test3\test4 got created
[debug] i.m.w.DirectoryWatcher - ENTRY_MODIFY [C:\Users\...\files\import\test\test1\test2\test3]
[debug] i.m.w.DirectoryWatcher - Failed to hash modified file [C:\Users\...\files\import\test\test1\test2\test3]. It may have been deleted.
[debug] i.m.w.DirectoryWatcher - ENTRY_CREATE [C:\Users\...\files\import\Neuer Ordner]
[debug] i.m.w.DirectoryWatcher - Registering [C:\Users\...\files\import\Neuer Ordner].
[info] a.FileImportService - C:\Users\...\files\import\Neuer Ordner got created
akkie commented 6 years ago

Tried to reproduce the issue with msys2 on windows:

[debug] i.m.w.DirectoryWatcher - ENTRY_CREATE [C:\Users\...\files\import\test1]
[debug] i.m.w.DirectoryWatcher - Registering [C:\Users\...\files\import\test1].
[info] a.FileImportService - C:\Users\...\files\import\test1 got created
[debug] i.m.w.DirectoryWatcher - ENTRY_CREATE [C:\Users\...\files\import\test1\test2]
[debug] i.m.w.DirectoryWatcher - Registering [C:\Users\...\files\import\test1\test2].
[info] a.FileImportService - C:\Users\...\files\import\test1\test2 got created
[debug] i.m.w.DirectoryWatcher - ENTRY_MODIFY [C:\Users\...\files\import\test1]
[info] a.FileImportService - C:\Users\...\files\import\test1 got modified
[debug] i.m.w.DirectoryWatcher - ENTRY_CREATE [C:\Users\...\files\import\test1\test2\test3]
[debug] i.m.w.DirectoryWatcher - Registering [C:\Users\...\files\import\test1\test2\test3].
[info] a.FileImportService - C:\Users\...\files\import\test1\test2\test3 got created
[debug] i.m.w.DirectoryWatcher - ENTRY_MODIFY [C:\Users\...\files\import\test1\test2]
[info] a.FileImportService - C:\Users\...\files\import\test1\test2 got modified
[debug] i.m.w.DirectoryWatcher - ENTRY_CREATE [C:\Users\...\files\import\test1\test2\test3\test4]
[debug] i.m.w.DirectoryWatcher - Registering [C:\Users\...\files\import\test1\test2\test3\test4].
[info] a.FileImportService - C:\Users\...\files\import\test1\test2\test3\test4 got created
[debug] i.m.w.DirectoryWatcher - ENTRY_MODIFY [C:\Users\...\files\import\test1\test2\test3]
[info] a.FileImportService - C:\Users\...\files\import\test1\test2\test3 got modified
[debug] i.m.w.DirectoryWatcher - ENTRY_DELETE [C:\Users\...\files\import\test1\test2\test3\test4]
[info] a.FileImportService - C:\Users\...\files\import\test1\test2\test3\test4 got deleted

The commands

import git:master ❯ mkdir test1
import git:master ❯ cd test1
test1 git:master ❯ mkdir test2
test1 git:master ❯ cd test2
test2 git:master ❯ mkdir test3
test2 git:master ❯ cd test3
test3 git:master ❯ mkdir test4 
test3 git:master ❯ cd ..
test2 git:master ❯ cd .. 
test1 git:master ❯ cd ..
import git:master ❯ rm -rf test1
import git:master ❯ mkdir test1
import git:master ❯ mkdir test2
gmethvin commented 6 years ago

@akkie Unfortunately I don't have a Windows 7 machine to test on, but haven't been able to repro on Windows 10, macOS or Linux.

Eventually I'd like to write some tests to trigger some of these weird edge cases so help would be appreciated.

akkie commented 6 years ago

@gmethvin With version 0.2.3-SNAPSHOT I can now see the exception that is thrown for the case. The exception is:

java.nio.file.FileSystemException: C:\Users\...\Neuer Ordner: The process cannot access the file because it is being used by another process.

        at sun.nio.fs.WindowsException.translateToIOException(Unknown Source)
        at sun.nio.fs.WindowsException.rethrowAsIOException(Unknown Source)
        at sun.nio.fs.WindowsException.rethrowAsIOException(Unknown Source)
        at sun.nio.fs.WindowsDirectoryStream.<init>(Unknown Source)
        at sun.nio.fs.WindowsFileSystemProvider.newDirectoryStream(Unknown Source)
        at java.nio.file.Files.newDirectoryStream(Unknown Source)
        at java.nio.file.FileTreeWalker.visit(Unknown Source)
        at java.nio.file.FileTreeWalker.walk(Unknown Source)
        at java.nio.file.Files.walkFileTree(Unknown Source)
        at java.nio.file.Files.walkFileTree(Unknown Source)
        at io.methvin.watcher.DirectoryWatcher.registerAll(DirectoryWatcher.java:203)
        at io.methvin.watcher.DirectoryWatcher.watch(DirectoryWatcher.java:135)
        at io.methvin.watcher.DirectoryWatcher.lambda$watchAsync$0(DirectoryWatcher.java:96)
        at java.util.concurrent.CompletableFuture$AsyncSupply.run(Unknown Source)

So the issue is that the watcher stops watching if a file or directory is locked on Windows. This can happen if a file is created or modified. I think a fix would be to check if the directory or file is locked, wait for the lock to release and watch it recursively again. The problem is still that the watcher cannot guarantee the notification for newly created files in a directory that has thrown an exception before, because if you wait for the lock to release, new files could already be created in the directory. This could be fixed if you keep an internal list of recognized files. If a creation event was triggered then you remove the file form the list. At the end you have a list of files for which no event were triggered.

This is the same issue as: https://github.com/pathikrit/better-files/issues/193

I think also it's general an issue with my use case, because it can always happen that not all newly created files will be recognized by the watcher, when copying a deeply nested directory structure into a watched directory. The issue is that the watcher must be faster with registering new watchers for recursive directories as files will be created in this directories. I think this is not possible with the current approach. If the watcher would automatically watch for recursive directories or files on the OS level, I think this issue wouldn't exists.

akkie commented 6 years ago

It seems that there exists a possibility to watch the complete file tree on supported systems with the ExtendedWatchEventModifier.FILE_TREE key.

http://mail.openjdk.java.net/pipermail/nio-dev/2011-January/001183.html

One thing I should have mentioned before is that our Windows WatchService implementation supports an implementation specific modifier that allows you to monitor a file tree with a single registration. If you want to try it out do this:

register(watcher, new WatchEvent.Kind<?>[]{ ENTRY_DELETE }, com.sun.nio.file.ExtendedWatchEventModifier.FILE_TREE);

With this modifier then you only register the top directory and the context for each event is the relative path from the top directory. It's not a portable solution and only works on Windows but it would be interesting to how it compares.

gmethvin commented 6 years ago

@akkie I also discovered that setting and was thinking to use it here. I will try it out but I was thinking of setting up a windows-based CI first.

akkie commented 6 years ago

Fixed by #2