diff options
-rwxr-xr-x | build.sc | 12 | ||||
-rw-r--r-- | clientserver/src/mill/clientserver/Client.java | 32 | ||||
-rw-r--r-- | clientserver/src/mill/clientserver/ClientServer.java | 8 | ||||
-rw-r--r-- | clientserver/src/mill/clientserver/Server.scala | 33 | ||||
-rw-r--r-- | main/src/mill/modules/Jvm.scala | 26 | ||||
-rw-r--r-- | main/test/src/mill/eval/JavaCompileJarTests.scala | 2 |
6 files changed, 81 insertions, 32 deletions
@@ -236,11 +236,13 @@ object dev extends MillModule{ write(outputPath, prependShellScript()) - val perms = java.nio.file.Files.getPosixFilePermissions(outputPath.toNIO) - perms.add(PosixFilePermission.GROUP_EXECUTE) - perms.add(PosixFilePermission.OWNER_EXECUTE) - perms.add(PosixFilePermission.OTHERS_EXECUTE) - java.nio.file.Files.setPosixFilePermissions(outputPath.toNIO, perms) + if (!scala.util.Properties.isWin) { + val perms = java.nio.file.Files.getPosixFilePermissions(outputPath.toNIO) + perms.add(PosixFilePermission.GROUP_EXECUTE) + perms.add(PosixFilePermission.OWNER_EXECUTE) + perms.add(PosixFilePermission.OTHERS_EXECUTE) + java.nio.file.Files.setPosixFilePermissions(outputPath.toNIO, perms) + } PathRef(outputPath) } diff --git a/clientserver/src/mill/clientserver/Client.java b/clientserver/src/mill/clientserver/Client.java index ed2fe6ad..248d3de1 100644 --- a/clientserver/src/mill/clientserver/Client.java +++ b/clientserver/src/mill/clientserver/Client.java @@ -1,9 +1,11 @@ package mill.clientserver; import io.github.retronym.java9rtexport.Export; -import org.scalasbt.ipcsocket.UnixDomainSocket; +import org.scalasbt.ipcsocket.*; import java.io.*; +import java.net.Socket; +import java.net.URISyntaxException; import java.net.URL; import java.nio.channels.FileChannel; import java.nio.file.Files; @@ -13,14 +15,15 @@ import java.util.Iterator; import java.util.Properties; public class Client { - static void initServer(String lockBase) throws IOException{ + + static void initServer(String lockBase) throws IOException,URISyntaxException{ ArrayList<String> selfJars = new ArrayList<String>(); ClassLoader current = Client.class.getClassLoader(); while(current != null){ if (current instanceof java.net.URLClassLoader) { URL[] urls = ((java.net.URLClassLoader) current).getURLs(); for (URL url: urls) { - selfJars.add(url.toString()); + selfJars.add(new File(url.toURI()).getCanonicalPath()); } } current = current.getParent(); @@ -71,7 +74,7 @@ public class Client { public void run() { try{ initServer(lockBase); - }catch(IOException e){ + }catch(Exception e){ throw new RuntimeException(e); } } @@ -100,16 +103,26 @@ public class Client { FileOutputStream f = new FileOutputStream(lockBase + "/run"); ClientServer.writeArgs(System.console() != null, args, f); f.close(); - if (locks.processLock.probe()) initServer.run(); + + boolean serverInit = false; + if (locks.processLock.probe()) { + serverInit = true; + initServer.run(); + } while(locks.processLock.probe()) Thread.sleep(3); + // Need to give sometime for Win32NamedPipeSocket to work + // if the server is just initialized + if (serverInit && ClientServer.isWindows) Thread.sleep(250); - UnixDomainSocket ioSocket = null; + Socket ioSocket = null; long retryStart = System.currentTimeMillis(); while(ioSocket == null && System.currentTimeMillis() - retryStart < 1000){ try{ - ioSocket = new UnixDomainSocket(lockBase + "/io"); + ioSocket = ClientServer.isWindows? + new Win32NamedPipeSocket(ClientServer.WIN32_PIPE_PREFIX + new File(lockBase).getName()) + : new UnixDomainSocket(lockBase + "/io"); }catch(Throwable e){ Thread.sleep(1); } @@ -187,7 +200,10 @@ class ClientOutputPumper implements Runnable{ } } }catch(IOException e){ - throw new RuntimeException(e); + // Win32NamedPipeSocket input stream somehow doesn't return -1, + // but throw IOException whose message contains "ReadFile()" with a ccode + if (ClientServer.isWindows && e.getMessage().contains("ReadFile()")) running = false; + else throw new RuntimeException(e); } } diff --git a/clientserver/src/mill/clientserver/ClientServer.java b/clientserver/src/mill/clientserver/ClientServer.java index a8692c61..7af5845b 100644 --- a/clientserver/src/mill/clientserver/ClientServer.java +++ b/clientserver/src/mill/clientserver/ClientServer.java @@ -6,6 +6,14 @@ import java.io.InputStream; import java.io.OutputStream; class ClientServer { + public static boolean isWindows = System.getProperty("os.name").toLowerCase().startsWith("windows"); + + // Windows named pipe prefix (see https://github.com/sbt/ipcsocket/blob/v1.0.0/README.md) + // Win32NamedPipeServerSocket automatically adds this as a prefix (if it is not already is prefixed), + // but Win32NamedPipeSocket does not + // https://github.com/sbt/ipcsocket/blob/v1.0.0/src/main/java/org/scalasbt/ipcsocket/Win32NamedPipeServerSocket.java#L36 + public static String WIN32_PIPE_PREFIX = "\\\\.\\pipe\\"; + public static String[] parseArgs(InputStream argStream) throws IOException { int argsLength = argStream.read(); diff --git a/clientserver/src/mill/clientserver/Server.scala b/clientserver/src/mill/clientserver/Server.scala index 27c43302..dde727df 100644 --- a/clientserver/src/mill/clientserver/Server.scala +++ b/clientserver/src/mill/clientserver/Server.scala @@ -3,7 +3,7 @@ package mill.clientserver import java.io._ import java.net.Socket -import org.scalasbt.ipcsocket.{UnixDomainServerSocket, UnixDomainSocket} +import org.scalasbt.ipcsocket._ trait ServerMain[T]{ def main(args0: Array[String]): Unit = { @@ -37,18 +37,28 @@ class Server[T](lockBase: String, var running = true while (running) { Server.lockBlock(locks.serverLock){ - new File(lockBase + "/io").delete() - val ioSocket = new UnixDomainServerSocket(lockBase + "/io") + val (serverSocket, socketClose) = if (ClientServer.isWindows) { + val socketName = ClientServer.WIN32_PIPE_PREFIX + new File(lockBase).getName + (new Win32NamedPipeServerSocket(socketName), () => new Win32NamedPipeSocket(socketName).close()) + } else { + val socketName = lockBase + "/io" + new File(socketName).delete() + (new UnixDomainServerSocket(socketName), () => new UnixDomainSocket(socketName).close()) + } + val sockOpt = Server.interruptWith( acceptTimeout, - new UnixDomainSocket(lockBase + "/io").close(), - ioSocket.accept() + socketClose(), + serverSocket.accept() ) sockOpt match{ case None => running = false case Some(sock) => - try handleRun(sock) + try { + handleRun(sock) + serverSocket.close() + } catch{case e: Throwable => e.printStackTrace(originalStdout) } } } @@ -106,7 +116,16 @@ class Server[T](lockBase: String, t.interrupt() t.stop() - clientSocket.close() + + if (ClientServer.isWindows) { + // Closing Win32NamedPipeSocket can often take ~5s + // It seems OK to exit the client early and subsequently + // start up mill client again (perhaps closing the server + // socket helps speed up the process). + val t = new Thread(() => clientSocket.close()) + t.setDaemon(true) + t.start() + } else clientSocket.close() } } object Server{ diff --git a/main/src/mill/modules/Jvm.scala b/main/src/mill/modules/Jvm.scala index dba3552d..291d4151 100644 --- a/main/src/mill/modules/Jvm.scala +++ b/main/src/mill/modules/Jvm.scala @@ -241,7 +241,7 @@ object Jvm { (implicit ctx: Ctx.Dest) = { val tmp = ctx.dest / "out-tmp.jar" - val baseUri = "jar:file:" + tmp + val baseUri = "jar:" + tmp.toIO.getCanonicalFile.toURI.toASCIIString val hm = new java.util.HashMap[String, String]() base match{ @@ -278,11 +278,13 @@ object Jvm { IO.stream(read.getInputStream(tmp), outputStream) outputStream.close() - val perms = Files.getPosixFilePermissions(output.toNIO) - perms.add(PosixFilePermission.GROUP_EXECUTE) - perms.add(PosixFilePermission.OWNER_EXECUTE) - perms.add(PosixFilePermission.OTHERS_EXECUTE) - Files.setPosixFilePermissions(output.toNIO, perms) + if (!scala.util.Properties.isWin) { + val perms = Files.getPosixFilePermissions(output.toNIO) + perms.add(PosixFilePermission.GROUP_EXECUTE) + perms.add(PosixFilePermission.OWNER_EXECUTE) + perms.add(PosixFilePermission.OTHERS_EXECUTE) + Files.setPosixFilePermissions(output.toNIO, perms) + } } PathRef(output) @@ -328,11 +330,13 @@ object Jvm { write(outputPath, launcherShellScript(mainClass, classPath.map(_.toString), jvmArgs)) - val perms = Files.getPosixFilePermissions(outputPath.toNIO) - perms.add(PosixFilePermission.GROUP_EXECUTE) - perms.add(PosixFilePermission.OWNER_EXECUTE) - perms.add(PosixFilePermission.OTHERS_EXECUTE) - Files.setPosixFilePermissions(outputPath.toNIO, perms) + if (!scala.util.Properties.isWin) { + val perms = Files.getPosixFilePermissions(outputPath.toNIO) + perms.add(PosixFilePermission.GROUP_EXECUTE) + perms.add(PosixFilePermission.OWNER_EXECUTE) + perms.add(PosixFilePermission.OTHERS_EXECUTE) + Files.setPosixFilePermissions(outputPath.toNIO, perms) + } PathRef(outputPath) } diff --git a/main/test/src/mill/eval/JavaCompileJarTests.scala b/main/test/src/mill/eval/JavaCompileJarTests.scala index 78cf09a5..1ac00c79 100644 --- a/main/test/src/mill/eval/JavaCompileJarTests.scala +++ b/main/test/src/mill/eval/JavaCompileJarTests.scala @@ -114,7 +114,7 @@ object JavaCompileJarTests extends TestSuite{ |test/FooTwo.class |hello.txt |""".stripMargin - assert(jarContents == expectedJarContents) + assert(jarContents.lines.toSeq == expectedJarContents.lines.toSeq) val executed = %%('java, "-cp", evaluator.outPath/'jar/'dest/"out.jar", "test.Foo")(evaluator.outPath).out.string assert(executed == (31337 + 271828) + System.lineSeparator) |