diff --git a/dist/package.mill b/dist/package.mill index 0ee1ca34cebc..0bdbcb133e18 100644 --- a/dist/package.mill +++ b/dist/package.mill @@ -9,6 +9,9 @@ import mill.util.Jvm import millbuild.* import mill.api.BuildCtx import scala.util.Using +import scala.util.Properties +import java.nio.file.Files +import java.nio.file.attribute.PosixFilePermission trait DistModule extends Module { // All modules that we want to aggregate as part of this `dev` assembly. @@ -19,9 +22,49 @@ trait DistModule extends Module { def executableRaw: T[PathRef] + def localRepo: T[PathRef] = Task { + val dest = Task.dest + val repos = Task.traverse(allPublishModules)(m => m.publishLocalTestRepo)().map(_.path) + for (repo <- repos; elem <- os.list(repo)) + os.copy.into(elem, dest, mergeFolders = true) + PathRef(dest) + } + def executable = Task { - Task.traverse(allPublishModules)(m => m.publishLocal(doc = false))() - executableRaw() + val rawExecutable = executableRaw() + if (Properties.isWin) { + val launcher = Task.dest / "mill.bat" + val launcherContent = + s"""@echo off + |set "NEW_COURSIER_REPOSITORIES=${localRepo().path.toNIO.toUri.toASCIIString}|ivy2Local|central" + |if defined COURSIER_REPOSITORIES ( + | set "NEW_COURSIER_REPOSITORIES=%NEW_COURSIER_REPOSITORIES%|%COURSIER_REPOSITORIES%" + |) else ( + | set "NEW_COURSIER_REPOSITORIES=%NEW_COURSIER_REPOSITORIES%|ivy2Local|central" + |) + |set "COURSIER_REPOSITORIES=%NEW_COURSIER_REPOSITORIES%" + |set NEW_COURSIER_REPOSITORIES= + |"${rawExecutable.path.toString.replace("\"", "\\\"")}" %* + |if errorlevel 1 exit /b %errorlevel% + |""".stripMargin + os.write(launcher, launcherContent) + PathRef(launcher) + } else { + val launcher = Task.dest / "mill" + val launcherContent = + s"""#!/usr/bin/env bash + |set -e + |export COURSIER_REPOSITORIES="${localRepo().path.toNIO.toUri.toASCIIString}|$${COURSIER_REPOSITORIES:-ivy2Local|central}" + |exec '${rawExecutable.path.toString.replace("'", "\\'")}' "$$@" + |""".stripMargin + os.write(launcher, launcherContent) + val perms = Files.getPosixFilePermissions(launcher.toNIO) + perms.add(PosixFilePermission.OWNER_EXECUTE) + perms.add(PosixFilePermission.GROUP_EXECUTE) + perms.add(PosixFilePermission.OTHERS_EXECUTE) + Files.setPosixFilePermissions(launcher.toNIO, perms) + PathRef(launcher) + } } def localBinName: String @@ -32,12 +75,15 @@ trait DistModule extends Module { * Build and install Mill locally. * * @param binFile The location where the Mill binary should be installed - * @param ivyRepo The local Ivy repository where Mill modules should be published to */ - def installLocal(binFile: String = localBinName, ivyRepo: String = null) = + def installLocal(binFile: String = localBinName) = { + val binFile0 = os.Path(binFile, BuildCtx.workspaceRoot) + val task = installIvyLocalTask(binFile0) Task.Command { - PathRef(installLocalTask(Task.Anon(binFile), ivyRepo)()) + task() + PathRef(binFile0) } + } val batExt = if (scala.util.Properties.isWin) ".bat" else "" @@ -53,16 +99,28 @@ trait DistModule extends Module { PathRef(path) } - def installLocalTask(binFile: Task[String], ivyRepo: String = null): Task[os.Path] = Task.Anon { - val targetFile = os.Path(binFile(), BuildCtx.workspaceRoot) - if (os.exists(targetFile)) - Task.log.info(s"Overwriting existing local Mill binary at ${targetFile}") - os.copy.over(executable().path, targetFile, createFolders = true) - Task.log.info( - s"Published ${build.dist.allPublishModules.size} modules and installed ${targetFile}" - ) - targetFile - } + def installLocalTask(binFile: Task[String]): Task[os.Path] = + Task.Anon { + val targetFile = os.Path(binFile(), BuildCtx.workspaceRoot) + if (os.exists(targetFile)) + Task.log.info(s"Overwriting existing local Mill binary at ${targetFile}") + os.copy.over(executable().path, targetFile, createFolders = true) + Task.log.info( + s"Published ${build.dist.allPublishModules.size} modules under Mill sources local repo ${localRepo().path} and installed ${targetFile}" + ) + targetFile + } + + def installIvyLocalTask(targetFile: os.Path): Task[Unit] = + Task.Anon { + if (os.exists(targetFile)) + Task.log.info(s"Overwriting existing local Mill binary at ${targetFile}") + Task.traverse(allPublishModules)(m => m.publishLocal(doc = false))() + os.copy.over(executableRaw().path, targetFile, createFolders = true) + Task.log.info( + s"Published ${build.dist.allPublishModules.size} modules under ~/.ivy2/local and installed ${targetFile}" + ) + } def artifactName: T[String] def artifact = Task { Artifact(Settings.pomOrg, artifactName(), build.millVersion()) } diff --git a/integration/ide/bsp-server/resources/snapshots/build-targets-jvm-test-environments.json b/integration/ide/bsp-server/resources/snapshots/build-targets-jvm-test-environments.json index 555076f46b88..c14bf2eee68f 100644 --- a/integration/ide/bsp-server/resources/snapshots/build-targets-jvm-test-environments.json +++ b/integration/ide/bsp-server/resources/snapshots/build-targets-jvm-test-environments.json @@ -18,7 +18,7 @@ "file:///workspace/app/test/compile-resources", "file:///workspace/app/test/resources", "file:///workspace/out/mill-bsp-out/app/test/compile.dest/classes", - "file:///user-home/.ivy2/local/com.lihaoyi/mill-libs-javalib-testrunner-entrypoint/SNAPSHOT/jars/mill-libs-javalib-testrunner-entrypoint.jar", + "file:///mill-workspace/out/dist/localRepo.dest/com/lihaoyi/mill-libs-javalib-testrunner-entrypoint/SNAPSHOT/mill-libs-javalib-testrunner-entrypoint-SNAPSHOT.jar", "file:///coursier-cache/https/repo1.maven.org/maven2/org/scala-sbt/test-interface/1.0/test-interface-1.0.jar" ], "jvmOptions": [], @@ -52,7 +52,7 @@ "file:///workspace/hello-java/test/compile-resources", "file:///workspace/hello-java/test/resources", "file:///workspace/out/mill-bsp-out/hello-java/test/compile.dest/classes", - "file:///user-home/.ivy2/local/com.lihaoyi/mill-libs-javalib-testrunner-entrypoint/SNAPSHOT/jars/mill-libs-javalib-testrunner-entrypoint.jar", + "file:///mill-workspace/out/dist/localRepo.dest/com/lihaoyi/mill-libs-javalib-testrunner-entrypoint/SNAPSHOT/mill-libs-javalib-testrunner-entrypoint-SNAPSHOT.jar", "file:///coursier-cache/https/repo1.maven.org/maven2/org/scala-sbt/test-interface/1.0/test-interface-1.0.jar" ], "jvmOptions": [], @@ -87,7 +87,7 @@ "file:///workspace/hello-scala/test/compile-resources", "file:///workspace/hello-scala/test/resources", "file:///workspace/out/mill-bsp-out/hello-scala/test/compile.dest/classes", - "file:///user-home/.ivy2/local/com.lihaoyi/mill-libs-javalib-testrunner-entrypoint/SNAPSHOT/jars/mill-libs-javalib-testrunner-entrypoint.jar", + "file:///mill-workspace/out/dist/localRepo.dest/com/lihaoyi/mill-libs-javalib-testrunner-entrypoint/SNAPSHOT/mill-libs-javalib-testrunner-entrypoint-SNAPSHOT.jar", "file:///coursier-cache/https/repo1.maven.org/maven2/org/scala-sbt/test-interface/1.0/test-interface-1.0.jar" ], "jvmOptions": [], diff --git a/integration/ide/build-classpath-contents/src/BuildClasspathContentsTests.scala b/integration/ide/build-classpath-contents/src/BuildClasspathContentsTests.scala index 37c1f30ec4c3..fad8eaa2ccec 100644 --- a/integration/ide/build-classpath-contents/src/BuildClasspathContentsTests.scala +++ b/integration/ide/build-classpath-contents/src/BuildClasspathContentsTests.scala @@ -18,37 +18,38 @@ object BuildClasspathContentsTests extends UtestIntegrationTestSuite { .filter(_.startsWith(BuildCtx.workspaceRoot)) .map(_.subRelativeTo(BuildCtx.workspaceRoot)) .filter(!_.startsWith("out/integration")) + .filter(!_.startsWith("out/dist/localRepo.dest")) .map(_.toString) .sorted if (sys.env("MILL_INTEGRATION_IS_PACKAGED_LAUNCHER") == "true") { assertGoldenLiteral( millPublishedJars, List( - "mill-core-api-daemon_3.jar", - "mill-core-api_3.jar", - "mill-core-constants.jar", - "mill-libs-androidlib-databinding_3.jar", - "mill-libs-androidlib_3.jar", - "mill-libs-daemon-client.jar", - "mill-libs-daemon-server_3.jar", - "mill-libs-javalib-api_3.jar", - "mill-libs-javalib-testrunner-entrypoint.jar", - "mill-libs-javalib-testrunner_3.jar", - "mill-libs-javalib_3.jar", - "mill-libs-javascriptlib_3.jar", - "mill-libs-kotlinlib-api_3.jar", - "mill-libs-kotlinlib-ksp2-api_3.jar", - "mill-libs-kotlinlib_3.jar", - "mill-libs-pythonlib_3.jar", - "mill-libs-rpc_3.jar", - "mill-libs-scalajslib-api_3.jar", - "mill-libs-scalajslib_3.jar", - "mill-libs-scalalib_3.jar", - "mill-libs-scalanativelib-api_3.jar", - "mill-libs-scalanativelib_3.jar", - "mill-libs-script_3.jar", - "mill-libs-util_3.jar", - "mill-libs_3.jar", + "mill-core-api-daemon_3-SNAPSHOT.jar", + "mill-core-api_3-SNAPSHOT.jar", + "mill-core-constants-SNAPSHOT.jar", + "mill-libs-androidlib-databinding_3-SNAPSHOT.jar", + "mill-libs-androidlib_3-SNAPSHOT.jar", + "mill-libs-daemon-client-SNAPSHOT.jar", + "mill-libs-daemon-server_3-SNAPSHOT.jar", + "mill-libs-javalib-api_3-SNAPSHOT.jar", + "mill-libs-javalib-testrunner-entrypoint-SNAPSHOT.jar", + "mill-libs-javalib-testrunner_3-SNAPSHOT.jar", + "mill-libs-javalib_3-SNAPSHOT.jar", + "mill-libs-javascriptlib_3-SNAPSHOT.jar", + "mill-libs-kotlinlib-api_3-SNAPSHOT.jar", + "mill-libs-kotlinlib-ksp2-api_3-SNAPSHOT.jar", + "mill-libs-kotlinlib_3-SNAPSHOT.jar", + "mill-libs-pythonlib_3-SNAPSHOT.jar", + "mill-libs-rpc_3-SNAPSHOT.jar", + "mill-libs-scalajslib-api_3-SNAPSHOT.jar", + "mill-libs-scalajslib_3-SNAPSHOT.jar", + "mill-libs-scalalib_3-SNAPSHOT.jar", + "mill-libs-scalanativelib-api_3-SNAPSHOT.jar", + "mill-libs-scalanativelib_3-SNAPSHOT.jar", + "mill-libs-script_3-SNAPSHOT.jar", + "mill-libs-util_3-SNAPSHOT.jar", + "mill-libs_3-SNAPSHOT.jar", "mill-moduledefs_3-0.11.10.jar" ) ) diff --git a/integration/ide/gen-idea/resources/extended/idea/mill_modules/mill-build.iml b/integration/ide/gen-idea/resources/extended/idea/mill_modules/mill-build.iml index b1cea1775c1b..dcaf14ec659e 100644 --- a/integration/ide/gen-idea/resources/extended/idea/mill_modules/mill-build.iml +++ b/integration/ide/gen-idea/resources/extended/idea/mill_modules/mill-build.iml @@ -53,38 +53,38 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/integration/ide/gen-idea/resources/extended/idea/mill_modules/mill-build.mill-build.iml b/integration/ide/gen-idea/resources/extended/idea/mill_modules/mill-build.mill-build.iml index bcdc6b4da6de..4cf3a039ce1f 100644 --- a/integration/ide/gen-idea/resources/extended/idea/mill_modules/mill-build.mill-build.iml +++ b/integration/ide/gen-idea/resources/extended/idea/mill_modules/mill-build.mill-build.iml @@ -54,41 +54,41 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + diff --git a/integration/ide/gen-idea/resources/hello-idea/idea/mill_modules/mill-build.iml b/integration/ide/gen-idea/resources/hello-idea/idea/mill_modules/mill-build.iml index fdf6a0bdf623..6b6c2c2d8efb 100644 --- a/integration/ide/gen-idea/resources/hello-idea/idea/mill_modules/mill-build.iml +++ b/integration/ide/gen-idea/resources/hello-idea/idea/mill_modules/mill-build.iml @@ -50,38 +50,38 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/integration/package.mill b/integration/package.mill index 016fb9f01bf1..83047da8a0e9 100644 --- a/integration/package.mill +++ b/integration/package.mill @@ -168,7 +168,10 @@ object `package` extends mill.Module { def testMill: T[PathRef] = { val name = if (scala.util.Properties.isWin) "mill.bat" else "mill" Task { - PathRef(build.dist.installLocalTask(binFile = Task.Anon((Task.dest / name).toString()))()) + val executable = build.dist.executable().path + val dest = Task.dest / name + os.copy.over(executable, dest) + PathRef(dest) } }