| author | wenzelm | 
| Wed, 17 Jun 2015 22:30:22 +0200 | |
| changeset 60511 | 5e67a223a141 | 
| parent 60263 | 2a5dbad75355 | 
| child 60970 | e08d868ceca9 | 
| permissions | -rw-r--r-- | 
| 40743 | 1 | (* Title: Pure/System/isabelle_system.ML | 
| 2 | Author: Makarius | |
| 3 | ||
| 4 | Isabelle system support. | |
| 5 | *) | |
| 6 | ||
| 7 | signature ISABELLE_SYSTEM = | |
| 8 | sig | |
| 9 | val isabelle_tool: string -> string -> int | |
| 10 | val mkdirs: Path.T -> unit | |
| 40745 | 11 | val mkdir: Path.T -> unit | 
| 40743 | 12 | val copy_dir: Path.T -> Path.T -> unit | 
| 56533 
cd8b6d849b6a
explicit 'document_files' in session ROOT specifications;
 wenzelm parents: 
56498diff
changeset | 13 | val copy_file: Path.T -> Path.T -> unit | 
| 
cd8b6d849b6a
explicit 'document_files' in session ROOT specifications;
 wenzelm parents: 
56498diff
changeset | 14 | val copy_file_base: Path.T * Path.T -> Path.T -> unit | 
| 42127 
8223e7f4b0da
Isabelle_System.create_tmp_path/with_tmp_file: optional extension;
 wenzelm parents: 
41944diff
changeset | 15 | val create_tmp_path: string -> string -> Path.T | 
| 
8223e7f4b0da
Isabelle_System.create_tmp_path/with_tmp_file: optional extension;
 wenzelm parents: 
41944diff
changeset | 16 | val with_tmp_file: string -> string -> (Path.T -> 'a) -> 'a | 
| 41307 
bb8468ae414e
slightly more standard Isabelle_System.with_tmp_file/with_tmp_dir (cf. Scala version);
 wenzelm parents: 
40785diff
changeset | 17 | val with_tmp_dir: string -> (Path.T -> 'a) -> 'a | 
| 43850 
7f2cbc713344
moved bash operations to Isabelle_System (cf. Scala version);
 wenzelm parents: 
43849diff
changeset | 18 | val bash_output: string -> string * int | 
| 
7f2cbc713344
moved bash operations to Isabelle_System (cf. Scala version);
 wenzelm parents: 
43849diff
changeset | 19 | val bash: string -> int | 
| 40743 | 20 | end; | 
| 21 | ||
| 22 | structure Isabelle_System: ISABELLE_SYSTEM = | |
| 23 | struct | |
| 24 | ||
| 43850 
7f2cbc713344
moved bash operations to Isabelle_System (cf. Scala version);
 wenzelm parents: 
43849diff
changeset | 25 | (* bash *) | 
| 
7f2cbc713344
moved bash operations to Isabelle_System (cf. Scala version);
 wenzelm parents: 
43849diff
changeset | 26 | |
| 
7f2cbc713344
moved bash operations to Isabelle_System (cf. Scala version);
 wenzelm parents: 
43849diff
changeset | 27 | fun bash_output s = | 
| 47499 
4b0daca2bf88
redirect bash stderr to Isabelle warning as appropriate -- avoid raw process error output which may either get ignored or overload PIDE syslog in extreme cases;
 wenzelm parents: 
46502diff
changeset | 28 | let | 
| 
4b0daca2bf88
redirect bash stderr to Isabelle warning as appropriate -- avoid raw process error output which may either get ignored or overload PIDE syslog in extreme cases;
 wenzelm parents: 
46502diff
changeset | 29 |     val {out, err, rc, ...} = Bash.process s;
 | 
| 
4b0daca2bf88
redirect bash stderr to Isabelle warning as appropriate -- avoid raw process error output which may either get ignored or overload PIDE syslog in extreme cases;
 wenzelm parents: 
46502diff
changeset | 30 | val _ = warning (trim_line err); | 
| 
4b0daca2bf88
redirect bash stderr to Isabelle warning as appropriate -- avoid raw process error output which may either get ignored or overload PIDE syslog in extreme cases;
 wenzelm parents: 
46502diff
changeset | 31 | in (out, rc) end; | 
| 43850 
7f2cbc713344
moved bash operations to Isabelle_System (cf. Scala version);
 wenzelm parents: 
43849diff
changeset | 32 | |
| 
7f2cbc713344
moved bash operations to Isabelle_System (cf. Scala version);
 wenzelm parents: 
43849diff
changeset | 33 | fun bash s = | 
| 47499 
4b0daca2bf88
redirect bash stderr to Isabelle warning as appropriate -- avoid raw process error output which may either get ignored or overload PIDE syslog in extreme cases;
 wenzelm parents: 
46502diff
changeset | 34 | let | 
| 
4b0daca2bf88
redirect bash stderr to Isabelle warning as appropriate -- avoid raw process error output which may either get ignored or overload PIDE syslog in extreme cases;
 wenzelm parents: 
46502diff
changeset | 35 | val (out, rc) = bash_output s; | 
| 
4b0daca2bf88
redirect bash stderr to Isabelle warning as appropriate -- avoid raw process error output which may either get ignored or overload PIDE syslog in extreme cases;
 wenzelm parents: 
46502diff
changeset | 36 | val _ = writeln (trim_line out); | 
| 
4b0daca2bf88
redirect bash stderr to Isabelle warning as appropriate -- avoid raw process error output which may either get ignored or overload PIDE syslog in extreme cases;
 wenzelm parents: 
46502diff
changeset | 37 | in rc end; | 
| 43850 
7f2cbc713344
moved bash operations to Isabelle_System (cf. Scala version);
 wenzelm parents: 
43849diff
changeset | 38 | |
| 
7f2cbc713344
moved bash operations to Isabelle_System (cf. Scala version);
 wenzelm parents: 
43849diff
changeset | 39 | |
| 40743 | 40 | (* system commands *) | 
| 41 | ||
| 42 | fun isabelle_tool name args = | |
| 43 | (case space_explode ":" (getenv "ISABELLE_TOOLS") |> get_first (fn dir => | |
| 43606 | 44 | let val path = File.platform_path (Path.append (Path.explode dir) (Path.basic name)) in | 
| 40743 | 45 | if can OS.FileSys.modTime path andalso | 
| 46 | not (OS.FileSys.isDir path) andalso | |
| 47 | OS.FileSys.access (path, [OS.FileSys.A_READ, OS.FileSys.A_EXEC]) | |
| 48 | then SOME path | |
| 49 | else NONE | |
| 50 | end handle OS.SysErr _ => NONE) of | |
| 51 | SOME path => bash (File.shell_quote path ^ " " ^ args) | |
| 47499 
4b0daca2bf88
redirect bash stderr to Isabelle warning as appropriate -- avoid raw process error output which may either get ignored or overload PIDE syslog in extreme cases;
 wenzelm parents: 
46502diff
changeset | 52 |   | NONE => (warning ("Unknown Isabelle tool: " ^ name); 2));
 | 
| 40743 | 53 | |
| 54 | fun system_command cmd = | |
| 55 |   if bash cmd <> 0 then error ("System command failed: " ^ cmd)
 | |
| 56 | else (); | |
| 57 | ||
| 58 | ||
| 59 | (* directory operations *) | |
| 60 | ||
| 60013 | 61 | fun mkdirs path = | 
| 60263 
2a5dbad75355
more portable mkdirs via perl, e.g. relevant for Windows UNC paths (network shares);
 wenzelm parents: 
60028diff
changeset | 62 | if File.is_dir path then () | 
| 
2a5dbad75355
more portable mkdirs via perl, e.g. relevant for Windows UNC paths (network shares);
 wenzelm parents: 
60028diff
changeset | 63 | else | 
| 
2a5dbad75355
more portable mkdirs via perl, e.g. relevant for Windows UNC paths (network shares);
 wenzelm parents: 
60028diff
changeset | 64 |    (bash ("perl -e \"use File::Path make_path; make_path(" ^ File.shell_path path ^ ");\"");
 | 
| 
2a5dbad75355
more portable mkdirs via perl, e.g. relevant for Windows UNC paths (network shares);
 wenzelm parents: 
60028diff
changeset | 65 |     if File.is_dir path then () else error ("Failed to create directory: " ^ Path.print path));
 | 
| 40743 | 66 | |
| 40785 | 67 | fun mkdir path = | 
| 68 | if File.is_dir path then () else OS.FileSys.mkDir (File.platform_path path); | |
| 40743 | 69 | |
| 70 | fun copy_dir src dst = | |
| 71 | if File.eq (src, dst) then () | |
| 46502 
3d43d4d4d071
more uniform / portable representation of the idea of "copy_dir" (NB: cp -f dereferences symlinks on GNU/Linux, but does not on old-school Unixen including BSD/Mac OS X);
 wenzelm parents: 
45199diff
changeset | 72 |   else (system_command ("cp -p -R -f " ^ File.shell_path src ^ "/. " ^ File.shell_path dst); ());
 | 
| 40743 | 73 | |
| 56533 
cd8b6d849b6a
explicit 'document_files' in session ROOT specifications;
 wenzelm parents: 
56498diff
changeset | 74 | fun copy_file src0 dst0 = | 
| 
cd8b6d849b6a
explicit 'document_files' in session ROOT specifications;
 wenzelm parents: 
56498diff
changeset | 75 | let | 
| 
cd8b6d849b6a
explicit 'document_files' in session ROOT specifications;
 wenzelm parents: 
56498diff
changeset | 76 | val src = Path.expand src0; | 
| 
cd8b6d849b6a
explicit 'document_files' in session ROOT specifications;
 wenzelm parents: 
56498diff
changeset | 77 | val dst = Path.expand dst0; | 
| 57085 
cb212f52c2a3
clarified copy_file: allow to rename base name, e.g. relevant for 'display_drafts';
 wenzelm parents: 
56533diff
changeset | 78 | val target = if File.is_dir dst then Path.append dst (Path.base src) else dst; | 
| 56533 
cd8b6d849b6a
explicit 'document_files' in session ROOT specifications;
 wenzelm parents: 
56498diff
changeset | 79 | in | 
| 
cd8b6d849b6a
explicit 'document_files' in session ROOT specifications;
 wenzelm parents: 
56498diff
changeset | 80 | if File.eq (src, target) then () | 
| 
cd8b6d849b6a
explicit 'document_files' in session ROOT specifications;
 wenzelm parents: 
56498diff
changeset | 81 | else | 
| 57085 
cb212f52c2a3
clarified copy_file: allow to rename base name, e.g. relevant for 'display_drafts';
 wenzelm parents: 
56533diff
changeset | 82 |       ignore (system_command ("cp -p -f " ^ File.shell_path src ^ " " ^ File.shell_path target))
 | 
| 56533 
cd8b6d849b6a
explicit 'document_files' in session ROOT specifications;
 wenzelm parents: 
56498diff
changeset | 83 | end; | 
| 
cd8b6d849b6a
explicit 'document_files' in session ROOT specifications;
 wenzelm parents: 
56498diff
changeset | 84 | |
| 
cd8b6d849b6a
explicit 'document_files' in session ROOT specifications;
 wenzelm parents: 
56498diff
changeset | 85 | fun copy_file_base (base_dir, src0) target_dir = | 
| 
cd8b6d849b6a
explicit 'document_files' in session ROOT specifications;
 wenzelm parents: 
56498diff
changeset | 86 | let | 
| 
cd8b6d849b6a
explicit 'document_files' in session ROOT specifications;
 wenzelm parents: 
56498diff
changeset | 87 | val src = Path.expand src0; | 
| 
cd8b6d849b6a
explicit 'document_files' in session ROOT specifications;
 wenzelm parents: 
56498diff
changeset | 88 | val src_dir = Path.dir src; | 
| 
cd8b6d849b6a
explicit 'document_files' in session ROOT specifications;
 wenzelm parents: 
56498diff
changeset | 89 | val _ = | 
| 
cd8b6d849b6a
explicit 'document_files' in session ROOT specifications;
 wenzelm parents: 
56498diff
changeset | 90 | if Path.starts_basic src then () | 
| 
cd8b6d849b6a
explicit 'document_files' in session ROOT specifications;
 wenzelm parents: 
56498diff
changeset | 91 |       else error ("Illegal path specification " ^ Path.print src ^ " beyond base directory");
 | 
| 
cd8b6d849b6a
explicit 'document_files' in session ROOT specifications;
 wenzelm parents: 
56498diff
changeset | 92 | val _ = mkdirs (Path.append target_dir src_dir); | 
| 
cd8b6d849b6a
explicit 'document_files' in session ROOT specifications;
 wenzelm parents: 
56498diff
changeset | 93 | in copy_file (Path.append base_dir src) (Path.append target_dir src) end; | 
| 
cd8b6d849b6a
explicit 'document_files' in session ROOT specifications;
 wenzelm parents: 
56498diff
changeset | 94 | |
| 41307 
bb8468ae414e
slightly more standard Isabelle_System.with_tmp_file/with_tmp_dir (cf. Scala version);
 wenzelm parents: 
40785diff
changeset | 95 | |
| 56498 | 96 | (* tmp files *) | 
| 41307 
bb8468ae414e
slightly more standard Isabelle_System.with_tmp_file/with_tmp_dir (cf. Scala version);
 wenzelm parents: 
40785diff
changeset | 97 | |
| 42127 
8223e7f4b0da
Isabelle_System.create_tmp_path/with_tmp_file: optional extension;
 wenzelm parents: 
41944diff
changeset | 98 | fun create_tmp_path name ext = | 
| 41307 
bb8468ae414e
slightly more standard Isabelle_System.with_tmp_file/with_tmp_dir (cf. Scala version);
 wenzelm parents: 
40785diff
changeset | 99 | let | 
| 42127 
8223e7f4b0da
Isabelle_System.create_tmp_path/with_tmp_file: optional extension;
 wenzelm parents: 
41944diff
changeset | 100 | val path = File.tmp_path (Path.basic (name ^ serial_string ()) |> Path.ext ext); | 
| 41307 
bb8468ae414e
slightly more standard Isabelle_System.with_tmp_file/with_tmp_dir (cf. Scala version);
 wenzelm parents: 
40785diff
changeset | 101 | val _ = File.exists path andalso | 
| 41944 
b97091ae583a
Path.print is the official way to show file-system paths to users -- note that Path.implode often indicates violation of the abstract datatype;
 wenzelm parents: 
41352diff
changeset | 102 |       raise Fail ("Temporary file already exists: " ^ Path.print path);
 | 
| 41307 
bb8468ae414e
slightly more standard Isabelle_System.with_tmp_file/with_tmp_dir (cf. Scala version);
 wenzelm parents: 
40785diff
changeset | 103 | in path end; | 
| 
bb8468ae414e
slightly more standard Isabelle_System.with_tmp_file/with_tmp_dir (cf. Scala version);
 wenzelm parents: 
40785diff
changeset | 104 | |
| 42127 
8223e7f4b0da
Isabelle_System.create_tmp_path/with_tmp_file: optional extension;
 wenzelm parents: 
41944diff
changeset | 105 | fun with_tmp_file name ext f = | 
| 
8223e7f4b0da
Isabelle_System.create_tmp_path/with_tmp_file: optional extension;
 wenzelm parents: 
41944diff
changeset | 106 | let val path = create_tmp_path name ext | 
| 
8223e7f4b0da
Isabelle_System.create_tmp_path/with_tmp_file: optional extension;
 wenzelm parents: 
41944diff
changeset | 107 | in Exn.release (Exn.capture f path before ignore (try File.rm path)) end; | 
| 41307 
bb8468ae414e
slightly more standard Isabelle_System.with_tmp_file/with_tmp_dir (cf. Scala version);
 wenzelm parents: 
40785diff
changeset | 108 | |
| 56498 | 109 | |
| 110 | (* tmp dirs *) | |
| 111 | ||
| 42127 
8223e7f4b0da
Isabelle_System.create_tmp_path/with_tmp_file: optional extension;
 wenzelm parents: 
41944diff
changeset | 112 | fun rm_tree path = system_command ("rm -r -f " ^ File.shell_path path);
 | 
| 41307 
bb8468ae414e
slightly more standard Isabelle_System.with_tmp_file/with_tmp_dir (cf. Scala version);
 wenzelm parents: 
40785diff
changeset | 113 | |
| 
bb8468ae414e
slightly more standard Isabelle_System.with_tmp_file/with_tmp_dir (cf. Scala version);
 wenzelm parents: 
40785diff
changeset | 114 | fun with_tmp_dir name f = | 
| 
bb8468ae414e
slightly more standard Isabelle_System.with_tmp_file/with_tmp_dir (cf. Scala version);
 wenzelm parents: 
40785diff
changeset | 115 | let | 
| 42127 
8223e7f4b0da
Isabelle_System.create_tmp_path/with_tmp_file: optional extension;
 wenzelm parents: 
41944diff
changeset | 116 | val path = create_tmp_path name ""; | 
| 41307 
bb8468ae414e
slightly more standard Isabelle_System.with_tmp_file/with_tmp_dir (cf. Scala version);
 wenzelm parents: 
40785diff
changeset | 117 | val _ = mkdirs path; | 
| 41352 
87adb55fb0fb
make SML/NJ and Poly/ML agree on the type of "before";
 wenzelm parents: 
41307diff
changeset | 118 | in Exn.release (Exn.capture f path before ignore (try rm_tree path)) end; | 
| 41307 
bb8468ae414e
slightly more standard Isabelle_System.with_tmp_file/with_tmp_dir (cf. Scala version);
 wenzelm parents: 
40785diff
changeset | 119 | |
| 40743 | 120 | end; | 
| 121 |