Fixes#3821
Initially I missed why #3821 was failing.
Looking at it again, the error message reads:
```
Caused by: java.lang.IllegalArgumentException: Interface (NGWin32NamedPipeLibrary) of library=kernel32 does not extend Library
at com.sun.jna.Native.loadLibrary(Native.java:566)
at sbt.internal.NGWin32NamedPipeLibrary.<clinit>(NGWin32NamedPipeLibrary.java:38)
... 7 more
```
Inside `Native.loadLibrary`, it requires the "library" interface to extend `com.sun.jna.Library`, which this adds.
There are just too many instances in which sbt's code relies on
the `lastModified`/`setLastModified` semantics, so instead of moving
to `get`/`setModifiedTime`, we use new IO calls that offer the new
timestamp precision, but retain the old semantics.
Previously I was seeing the error upon the first scripted test. I thought it was because Main was somehow not early enough. It might just be because scripted technically runs as part of the build.
Ref sbt/io#110
Fixes#3823
When you launch a second instance of sbt on a build, prior to this change it was displaying `java.io.IOException: sbt server is already running` on every command. This make it a bit less aggressive, and just display a warning once.
```
[warn] Is another instance of sbt is running on this build?
[warn] Running multiple instances is unsupported
```
It turns out the code in Sync.scala activiely tries to transfer
the invalid modifed time of non-existent files in the source
directory over the time of the target file, which may or may
not exist. In case it exists, the modification time is set
to January 1, 1970. This is arguably a bug in Sync, which
should be adjusted to better handle mappings with source
files that do not exist. For now, however, we preserve the
current behavior, using the deprecated copyLastModified().
In Eval there is a calculation of hashes by scanning the elements
of classpath, and getting the last modification time of each
directory. When lastModified() was in use, non-existent elements
would return 0L, but getModifiedTime() will throw an exception
instead (like getLastModifiedTime(), incidentally).
So, we catch the FileNotFoundException and return 0L now as well.
This is to avoid it initialising Log4J2 (via SLF4J), which we initialise
ourselves programmatically in LogExchange. Also there's no need to
removeAll in initialState.
Fixes#3787
Ref https://github.com/sbt/io/pull/96
Under RFC 8089, both u1 and u3 are legal, but many of the other platforms expect traditional u3.
This will increase the compatibility/usability of sbt server, for example to integrate with Vim.
Although in theory the fix in #3776 should be preferable to
synchronize templateStats() manually, it turns out that we
still get errors in some tests. So, reverting to a
synchronized section while we investigate.
This reverts commit ee90917cc4.
Currently the server will try to start even if there are existing sbt sessions. This causes the second session to take over the server for Unix domain socket.
This adds a check before the server comes up and make sure that the socket is not taken.
Fixes#3786
To configure the log level of the server, this introduces a new task key named `serverLog`. The idea is to set this using `Global / serverLog / logLevel`. It will also check the global log level, and if all else fails, fallback to Warn.
```
lazy val level: Level.Value = (s get serverLogLevel) orElse (s get logLevel) match {
case Some(x) => x
case None => Level.Warn
}
```