more Isabelle/ML/Scala operations;
authorwenzelm
Sat, 27 Feb 2021 21:01:07 +0100
changeset 73322 5b15eee1a661
parent 73321 0b8411b27059
child 73323 c2ab1a970e82
more Isabelle/ML/Scala operations; clarified errors;
NEWS
src/Pure/System/isabelle_system.ML
src/Pure/System/isabelle_system.scala
src/Pure/System/scala.scala
--- a/NEWS	Sat Feb 27 20:49:38 2021 +0100
+++ b/NEWS	Sat Feb 27 21:01:07 2021 +0100
@@ -66,6 +66,14 @@
 available, CPU time is only available on Linux and macOS, GC time is
 unavailable.
 
+* Likewise, the following Isabelle/ML system operations are run in the
+context of Isabelle/Scala:
+
+  - Isabelle_System.make_directory
+  - Isabelle_System.copy_dir
+  - Isabelle_System.copy_file
+  - Isabelle_System.copy_base_file
+
 
 
 New in Isabelle2021 (February 2021)
--- a/src/Pure/System/isabelle_system.ML	Sat Feb 27 20:49:38 2021 +0100
+++ b/src/Pure/System/isabelle_system.ML	Sat Feb 27 21:01:07 2021 +0100
@@ -69,39 +69,24 @@
     (bash_functions () |> map (rpair Position.none)) ctxt arg;
 
 
-(* directory operations *)
+(* directory and file operations *)
+
+fun scala_function name args =
+  ignore (Scala.function name (space_implode "\000" (map (Path.implode o File.absolute_path) args)));
 
 fun system_command cmd =
   if bash cmd <> 0 then error ("System command failed: " ^ cmd) else ();
 
 fun rm_tree path = system_command ("rm -r -f " ^ File.bash_path path);
 
-fun make_directory path =
-  (Scala.function "make_directory" (Path.implode (File.absolute_path path)); path);
+fun make_directory path = (scala_function "make_directory" [path]; path);
 
-fun copy_dir src dst =
-  if File.eq (src, dst) then ()
-  else (system_command ("cp -p -R -f " ^ File.bash_path src ^ "/. " ^ File.bash_path dst); ());
+fun copy_dir src dst = scala_function "copy_dir" [src, dst];
 
-fun copy_file src0 dst0 =
-  let
-    val src = Path.expand src0;
-    val dst = Path.expand dst0;
-    val target = if File.is_dir dst then dst + Path.base src else dst;
-  in
-    if File.eq (src, target) then ()
-    else
-      ignore (system_command ("cp -p -f " ^ File.bash_path src ^ " " ^ File.bash_path target))
-  end;
+fun copy_file src dst = scala_function "copy_file" [src, dst];
 
-fun copy_file_base (base_dir, src0) target_dir =
-  let
-    val src = Path.expand src0;
-    val src_dir = Path.dir src;
-    val _ =
-      if Path.starts_basic src then ()
-      else error ("Illegal path specification " ^ Path.print src ^ " beyond base directory");
-  in copy_file (base_dir + src) (make_directory (target_dir + src_dir)) end;
+fun copy_file_base (base_dir, src) target_dir =
+  scala_function "copy_file_base" [base_dir, src, target_dir];
 
 
 (* tmp files *)
--- a/src/Pure/System/isabelle_system.scala	Sat Feb 27 20:49:38 2021 +0100
+++ b/src/Pure/System/isabelle_system.scala	Sat Feb 27 21:01:07 2021 +0100
@@ -180,6 +180,21 @@
 
   /** file-system operations **/
 
+  /* scala functions */
+
+  private def apply_paths(arg: String, fun: List[Path] => Unit): String =
+    { fun(Library.space_explode('\u0000', arg).map(Path.explode)); "" }
+
+  private def apply_paths1(arg: String, fun: Path => Unit): String =
+    apply_paths(arg, { case List(path) => fun(path) })
+
+  private def apply_paths2(arg: String, fun: (Path, Path) => Unit): String =
+    apply_paths(arg, { case List(path1, path2) => fun(path1, path2) })
+
+  private def apply_paths3(arg: String, fun: (Path, Path, Path) => Unit): String =
+    apply_paths(arg, { case List(path1, path2, path3) => fun(path1, path2, path3) })
+
+
   /* permissions */
 
   def chmod(arg: String, path: Path): Unit =
@@ -198,30 +213,48 @@
     path
   }
 
-  object Make_Directory extends Scala.Fun("make_directory")
-  {
-    val here = Scala_Project.here
-    def apply(arg: String): String = { make_directory(Path.explode(arg)); "" }
-  }
-
   def new_directory(path: Path): Path =
     if (path.is_dir) error("Directory already exists: " + path.absolute)
     else make_directory(path)
 
+  def copy_dir(dir1: Path, dir2: Path): Unit =
+  {
+    val res = bash("cp -a " + File.bash_path(dir1) + " " + File.bash_path(dir2))
+    if (!res.ok) {
+      cat_error("Failed to copy directory " + dir1.absolute + " to " + dir2.absolute, res.err)
+    }
+  }
 
 
-  /* copy */
+  object Make_Directory extends Scala.Fun("make_directory")
+  {
+    val here = Scala_Project.here
+    def apply(arg: String): String = apply_paths1(arg, make_directory)
+  }
 
-  def copy_dir(dir1: Path, dir2: Path): Unit =
-    bash("cp -a " + File.bash_path(dir1) + " " + File.bash_path(dir2)).check
+  object Copy_Dir extends Scala.Fun("copy_dir")
+  {
+    val here = Scala_Project.here
+    def apply(arg: String): String = apply_paths2(arg, copy_dir)
+  }
+
+
+  /* copy files */
 
   def copy_file(src: JFile, dst: JFile): Unit =
   {
     val target = if (dst.isDirectory) new JFile(dst, src.getName) else dst
     if (!File.eq(src, target)) {
-      Files.copy(src.toPath, target.toPath,
-        StandardCopyOption.COPY_ATTRIBUTES,
-        StandardCopyOption.REPLACE_EXISTING)
+      try {
+        Files.copy(src.toPath, target.toPath,
+          StandardCopyOption.COPY_ATTRIBUTES,
+          StandardCopyOption.REPLACE_EXISTING)
+      }
+      catch {
+        case ERROR(msg) =>
+          cat_error("Failed top copy file " +
+            File.path(src).absolute + " to " + File.path(dst).absolute, msg)
+      }
     }
   }
 
@@ -236,7 +269,20 @@
   }
 
 
-  /* move */
+  object Copy_File extends Scala.Fun("copy_file")
+  {
+    val here = Scala_Project.here
+    def apply(arg: String): String = apply_paths2(arg, copy_file)
+  }
+
+  object Copy_File_Base extends Scala.Fun("copy_file_base")
+  {
+    val here = Scala_Project.here
+    def apply(arg: String): String = apply_paths3(arg, copy_file_base)
+  }
+
+
+  /* move files */
 
   def move_file(src: JFile, dst: JFile)
   {
--- a/src/Pure/System/scala.scala	Sat Feb 27 20:49:38 2021 +0100
+++ b/src/Pure/System/scala.scala	Sat Feb 27 21:01:07 2021 +0100
@@ -246,4 +246,7 @@
   Bash.Process,
   Bibtex.Check_Database,
   Isabelle_System.Make_Directory,
+  Isabelle_System.Copy_Dir,
+  Isabelle_System.Copy_File,
+  Isabelle_System.Copy_File_Base,
   Isabelle_Tool.Isabelle_Tools)