support for existing Node.js directory;
authorwenzelm
Tue, 09 Sep 2025 21:49:11 +0200
changeset 83121 74a25a7c2481
parent 83120 402f51de0347
child 83122 766f732d7705
support for existing Node.js directory;
src/Pure/System/nodejs.scala
src/Tools/VSCode/src/component_vscodium.scala
--- a/src/Pure/System/nodejs.scala	Tue Sep 09 17:39:04 2025 +0200
+++ b/src/Pure/System/nodejs.scala	Tue Sep 09 21:49:11 2025 +0200
@@ -46,6 +46,12 @@
     }
   }
 
+  def directory(platform_context: Isabelle_Platform.Context, path: Path): Directory = {
+    val node_dir = new Directory(platform_context, path)
+    val node_exe = node_dir.bin_dir + Path.basic("node").exe_if(node_dir.platform.is_windows)
+    if (node_exe.is_file) node_dir else error("Bad Node.js directory " + path)
+  }
+
   class Directory private[Nodejs](
     val platform_context: Isabelle_Platform.Context,
     val path: Path
--- a/src/Tools/VSCode/src/component_vscodium.scala	Tue Sep 09 17:39:04 2025 +0200
+++ b/src/Tools/VSCode/src/component_vscodium.scala	Tue Sep 09 21:49:11 2025 +0200
@@ -124,7 +124,8 @@
   object Build_Context {
     def make(
       platform_context: Isabelle_Platform.Context,
-      node_version: String = default_node_version,
+      node_root: Option[Path] = None,
+      node_version: String = "",
       vscodium_version: String = default_vscodium_version
     ): Build_Context = {
       val platform = platform_context.isabelle_platform
@@ -143,12 +144,14 @@
         }
         else if (platform.is_linux) List("SKIP_LINUX_PACKAGES=True")
         else Nil
-      Build_Context(platform_context, node_version, vscodium_version, env1 ::: env2)
+      val node_version1 = proper_string(node_version).getOrElse(default_node_version)
+      Build_Context(platform_context, node_root, node_version1, vscodium_version, env1 ::: env2)
     }
   }
 
   sealed case class Build_Context(
     platform_context: Isabelle_Platform.Context,
+    node_root: Option[Path],
     node_version: String,
     vscodium_version: String,
     env: List[String]
@@ -157,10 +160,14 @@
     def progress: Progress = platform_context.progress
 
     def node_setup(base_dir: Path): Nodejs.Directory =
-      Nodejs.setup(base_dir,
-        platform_context = platform_context,
-        version = node_version,
-        packages = List("yarn"))
+      node_root match {
+        case Some(path) => Nodejs.directory(platform_context, path)
+        case None =>
+          Nodejs.setup(base_dir,
+            platform_context = platform_context,
+            version = node_version,
+            packages = List("yarn"))
+      }
 
     def download_ext: String = if (platform.is_linux) "tar.gz" else "zip"
 
@@ -320,6 +327,7 @@
 
   def component_vscodium(
     target_dir: Path = Path.current,
+    node_root: Option[Path] = None,
     node_version: String = default_node_version,
     vscodium_version: String = default_vscodium_version,
     platform_context: Isabelle_Platform.Context = Isabelle_Platform.Context(),
@@ -329,6 +337,7 @@
 
     val build_context =
       Build_Context.make(platform_context,
+        node_root = node_root,
         node_version = node_version,
         vscodium_version = vscodium_version)
 
@@ -449,6 +458,7 @@
         var mingw = MinGW.none
         var node_version = default_node_version
         var vscodium_version = default_vscodium_version
+        var node_root: Option[Path] = None
         var verbose = false
 
         val getopts = Getopts("""
@@ -457,8 +467,10 @@
   Options are:
     -D DIR       target directory (default ".")
     -M DIR       msys/mingw root specification for Windows
-    -N VERSION   Node.js version (default: """" + default_node_version + """")
+    -N VERSION   download Node.js version (overrides option -n)
+                 (default: """" + default_node_version + """")
     -V VERSION   VSCodium version (default: """" + default_vscodium_version + """")
+    -n DIR       use existing Node.js directory (overrides option -N)
     -v           verbose
 
   Build VSCodium from sources and turn it into an Isabelle component.
@@ -486,8 +498,9 @@
 """,
           "D:" -> (arg => target_dir = Path.explode(arg)),
           "M:" -> (arg => mingw = MinGW(Path.explode(arg))),
-          "N:" -> (arg => node_version = arg),
+          "N:" -> { arg => node_version = arg; node_root = None },
           "V:" -> (arg => vscodium_version = arg),
+          "n:" -> { arg => node_root = Some(Path.explode(arg)); node_version = "" },
           "v" -> (_ => verbose = true))
 
         val more_args = getopts(args)
@@ -496,8 +509,9 @@
         val progress = new Console_Progress(verbose = verbose)
         val platform_context = Isabelle_Platform.Context(mingw = mingw, progress = progress)
 
-        component_vscodium(target_dir = target_dir, node_version = node_version,
-          vscodium_version = vscodium_version, platform_context = platform_context)
+        component_vscodium(target_dir = target_dir, node_root = node_root,
+          node_version = node_version, vscodium_version = vscodium_version,
+          platform_context = platform_context)
       })
 
   val isabelle_tool2 =