| author | wenzelm | 
| Tue, 06 Sep 2022 11:55:24 +0200 | |
| changeset 76070 | cf13b2147c48 | 
| parent 75616 | 986506233812 | 
| child 76884 | a004c5322ea4 | 
| permissions | -rw-r--r-- | 
| 6118 | 1 | (* Title: Pure/General/file.ML | 
| 64698 | 2 | Author: Makarius | 
| 5009 | 3 | |
| 64698 | 4 | File-system operations. | 
| 5009 | 5 | *) | 
| 6 | ||
| 7 | signature FILE = | |
| 8 | sig | |
| 60970 
e08d868ceca9
clarified File.standard_path vs. File.platform_path (like Isabelle/Scala operations);
 wenzelm parents: 
59058diff
changeset | 9 | val standard_path: Path.T -> string | 
| 16261 | 10 | val platform_path: Path.T -> string | 
| 62549 
9498623b27f0
File.bash_string operations in ML as in Scala -- exclusively for GNU bash, not perl and not user output;
 wenzelm parents: 
62468diff
changeset | 11 | val bash_path: Path.T -> string | 
| 69223 | 12 | val bash_paths: Path.T list -> string | 
| 72278 | 13 | val bash_platform_path: Path.T -> string | 
| 73314 
87403fde8cc3
more direct make_directory in ML and Scala, but ssh still requires perl for Windows UNC paths (see a5dbad753552);
 wenzelm parents: 
73264diff
changeset | 14 | val absolute_path: Path.T -> Path.T | 
| 42003 
6e45dc518ebb
replaced File.check by specific File.check_file, File.check_dir;
 wenzelm parents: 
41944diff
changeset | 15 | val full_path: Path.T -> Path.T -> Path.T | 
| 6182 | 16 | val tmp_path: Path.T -> Path.T | 
| 17826 | 17 | val exists: Path.T -> bool | 
| 18 | val rm: Path.T -> unit | |
| 40785 | 19 | val is_dir: Path.T -> bool | 
| 69300 
8b6ab9989bcd
is_file/is_dir/read_dir: more uniform treatment of errors and boundary cases, notably for symlinks in ssh;
 wenzelm parents: 
69223diff
changeset | 20 | val is_file: Path.T -> bool | 
| 42003 
6e45dc518ebb
replaced File.check by specific File.check_file, File.check_dir;
 wenzelm parents: 
41944diff
changeset | 21 | val check_dir: Path.T -> Path.T | 
| 
6e45dc518ebb
replaced File.check by specific File.check_file, File.check_dir;
 wenzelm parents: 
41944diff
changeset | 22 | val check_file: Path.T -> Path.T | 
| 43848 | 23 | val fold_dir: (string -> 'a -> 'a) -> Path.T -> 'a -> 'a | 
| 24 | val read_dir: Path.T -> string list | |
| 75616 
986506233812
clarified signature: File.read_lines is based on scalable Bytes.T;
 wenzelm parents: 
75615diff
changeset | 25 | val read: Path.T -> string | 
| 43848 | 26 | val read_lines: Path.T -> string list | 
| 6182 | 27 | val write: Path.T -> string -> unit | 
| 28 | val append: Path.T -> string -> unit | |
| 16713 | 29 | val write_list: Path.T -> string list -> unit | 
| 30 | val append_list: Path.T -> string list -> unit | |
| 16603 | 31 | val eq: Path.T * Path.T -> bool | 
| 5009 | 32 | end; | 
| 33 | ||
| 34 | structure File: FILE = | |
| 35 | struct | |
| 36 | ||
| 26503 
4dec4460244f
discontinued unused hooks explode_platform_path_fn, platform_path_fn, shell_path_fn;
 wenzelm parents: 
26220diff
changeset | 37 | (* system path representations *) | 
| 6224 | 38 | |
| 60970 
e08d868ceca9
clarified File.standard_path vs. File.platform_path (like Isabelle/Scala operations);
 wenzelm parents: 
59058diff
changeset | 39 | val standard_path = Path.implode o Path.expand; | 
| 62468 | 40 | val platform_path = ML_System.platform_path o standard_path; | 
| 26980 
f7f48bb9a025
ident: naive caching prevents potentially slow external invocations;
 wenzelm parents: 
26946diff
changeset | 41 | |
| 73264 | 42 | val bash_path = Bash.string o standard_path; | 
| 43 | val bash_paths = Bash.strings o map standard_path; | |
| 6224 | 44 | |
| 73264 | 45 | val bash_platform_path = Bash.string o platform_path; | 
| 72278 | 46 | |
| 70292 | 47 | |
| 42003 
6e45dc518ebb
replaced File.check by specific File.check_file, File.check_dir;
 wenzelm parents: 
41944diff
changeset | 48 | (* full_path *) | 
| 
6e45dc518ebb
replaced File.check by specific File.check_file, File.check_dir;
 wenzelm parents: 
41944diff
changeset | 49 | |
| 73314 
87403fde8cc3
more direct make_directory in ML and Scala, but ssh still requires perl for Windows UNC paths (see a5dbad753552);
 wenzelm parents: 
73264diff
changeset | 50 | val absolute_path = | 
| 
87403fde8cc3
more direct make_directory in ML and Scala, but ssh still requires perl for Windows UNC paths (see a5dbad753552);
 wenzelm parents: 
73264diff
changeset | 51 | Path.expand #> (fn path => | 
| 
87403fde8cc3
more direct make_directory in ML and Scala, but ssh still requires perl for Windows UNC paths (see a5dbad753552);
 wenzelm parents: 
73264diff
changeset | 52 | if Path.is_absolute path then path | 
| 
87403fde8cc3
more direct make_directory in ML and Scala, but ssh still requires perl for Windows UNC paths (see a5dbad753552);
 wenzelm parents: 
73264diff
changeset | 53 | else Path.explode (ML_System.standard_path (OS.FileSys.getDir ())) + path); | 
| 
87403fde8cc3
more direct make_directory in ML and Scala, but ssh still requires perl for Windows UNC paths (see a5dbad753552);
 wenzelm parents: 
73264diff
changeset | 54 | |
| 42003 
6e45dc518ebb
replaced File.check by specific File.check_file, File.check_dir;
 wenzelm parents: 
41944diff
changeset | 55 | fun full_path dir path = | 
| 
6e45dc518ebb
replaced File.check by specific File.check_file, File.check_dir;
 wenzelm parents: 
41944diff
changeset | 56 | let | 
| 
6e45dc518ebb
replaced File.check by specific File.check_file, File.check_dir;
 wenzelm parents: 
41944diff
changeset | 57 | val path' = Path.expand path; | 
| 
6e45dc518ebb
replaced File.check by specific File.check_file, File.check_dir;
 wenzelm parents: 
41944diff
changeset | 58 | val _ = Path.is_current path' andalso error "Bad file specification"; | 
| 73314 
87403fde8cc3
more direct make_directory in ML and Scala, but ssh still requires perl for Windows UNC paths (see a5dbad753552);
 wenzelm parents: 
73264diff
changeset | 59 | in absolute_path (dir + path') end; | 
| 5009 | 60 | |
| 6182 | 61 | |
| 62 | (* tmp_path *) | |
| 63 | ||
| 72511 
460d743010bc
clarified signature: overloaded "+" for Path.append;
 wenzelm parents: 
72278diff
changeset | 64 | fun tmp_path path = Path.variable "ISABELLE_TMP" + Path.base path; | 
| 5009 | 65 | |
| 66 | ||
| 26980 
f7f48bb9a025
ident: naive caching prevents potentially slow external invocations;
 wenzelm parents: 
26946diff
changeset | 67 | (* directory entries *) | 
| 
f7f48bb9a025
ident: naive caching prevents potentially slow external invocations;
 wenzelm parents: 
26946diff
changeset | 68 | |
| 23861 
72bb3494746f
replaced info by ident (for full identification, potentially content-based);
 wenzelm parents: 
23826diff
changeset | 69 | val exists = can OS.FileSys.modTime o platform_path; | 
| 16261 | 70 | |
| 71 | val rm = OS.FileSys.remove o platform_path; | |
| 72 | ||
| 69300 
8b6ab9989bcd
is_file/is_dir/read_dir: more uniform treatment of errors and boundary cases, notably for symlinks in ssh;
 wenzelm parents: 
69223diff
changeset | 73 | fun test_dir path = the_default false (try OS.FileSys.isDir (platform_path path)); | 
| 
8b6ab9989bcd
is_file/is_dir/read_dir: more uniform treatment of errors and boundary cases, notably for symlinks in ssh;
 wenzelm parents: 
69223diff
changeset | 74 | fun is_dir path = exists path andalso test_dir path; | 
| 
8b6ab9989bcd
is_file/is_dir/read_dir: more uniform treatment of errors and boundary cases, notably for symlinks in ssh;
 wenzelm parents: 
69223diff
changeset | 75 | fun is_file path = exists path andalso not (test_dir path); | 
| 40785 | 76 | |
| 42003 
6e45dc518ebb
replaced File.check by specific File.check_file, File.check_dir;
 wenzelm parents: 
41944diff
changeset | 77 | fun check_dir path = | 
| 69300 
8b6ab9989bcd
is_file/is_dir/read_dir: more uniform treatment of errors and boundary cases, notably for symlinks in ssh;
 wenzelm parents: 
69223diff
changeset | 78 | if is_dir path then path | 
| 63668 | 79 |   else error ("No such directory: " ^ Path.print (Path.expand path));
 | 
| 42003 
6e45dc518ebb
replaced File.check by specific File.check_file, File.check_dir;
 wenzelm parents: 
41944diff
changeset | 80 | |
| 
6e45dc518ebb
replaced File.check by specific File.check_file, File.check_dir;
 wenzelm parents: 
41944diff
changeset | 81 | fun check_file path = | 
| 69300 
8b6ab9989bcd
is_file/is_dir/read_dir: more uniform treatment of errors and boundary cases, notably for symlinks in ssh;
 wenzelm parents: 
69223diff
changeset | 82 | if is_file path then path | 
| 63668 | 83 |   else error ("No such file: " ^ Path.print (Path.expand path));
 | 
| 42003 
6e45dc518ebb
replaced File.check by specific File.check_file, File.check_dir;
 wenzelm parents: 
41944diff
changeset | 84 | |
| 16261 | 85 | |
| 43848 | 86 | (* directory content *) | 
| 87 | ||
| 69300 
8b6ab9989bcd
is_file/is_dir/read_dir: more uniform treatment of errors and boundary cases, notably for symlinks in ssh;
 wenzelm parents: 
69223diff
changeset | 88 | fun fold_dir f path a = | 
| 75615 | 89 | check_dir path |> File_Stream.open_dir (fn stream => | 
| 69300 
8b6ab9989bcd
is_file/is_dir/read_dir: more uniform treatment of errors and boundary cases, notably for symlinks in ssh;
 wenzelm parents: 
69223diff
changeset | 90 | let | 
| 
8b6ab9989bcd
is_file/is_dir/read_dir: more uniform treatment of errors and boundary cases, notably for symlinks in ssh;
 wenzelm parents: 
69223diff
changeset | 91 | fun read x = | 
| 
8b6ab9989bcd
is_file/is_dir/read_dir: more uniform treatment of errors and boundary cases, notably for symlinks in ssh;
 wenzelm parents: 
69223diff
changeset | 92 | (case OS.FileSys.readDir stream of | 
| 
8b6ab9989bcd
is_file/is_dir/read_dir: more uniform treatment of errors and boundary cases, notably for symlinks in ssh;
 wenzelm parents: 
69223diff
changeset | 93 | NONE => x | 
| 
8b6ab9989bcd
is_file/is_dir/read_dir: more uniform treatment of errors and boundary cases, notably for symlinks in ssh;
 wenzelm parents: 
69223diff
changeset | 94 | | SOME entry => read (f entry x)); | 
| 
8b6ab9989bcd
is_file/is_dir/read_dir: more uniform treatment of errors and boundary cases, notably for symlinks in ssh;
 wenzelm parents: 
69223diff
changeset | 95 | in read a end); | 
| 43848 | 96 | |
| 69427 
ff2f39a221d4
clarified operations: uniform sorting of results;
 wenzelm parents: 
69300diff
changeset | 97 | fun read_dir path = sort_strings (fold_dir cons path []); | 
| 43848 | 98 | |
| 99 | ||
| 75616 
986506233812
clarified signature: File.read_lines is based on scalable Bytes.T;
 wenzelm parents: 
75615diff
changeset | 100 | (* read *) | 
| 43848 | 101 | |
| 75615 | 102 | val read = File_Stream.open_input File_Stream.input_all; | 
| 5009 | 103 | |
| 75616 
986506233812
clarified signature: File.read_lines is based on scalable Bytes.T;
 wenzelm parents: 
75615diff
changeset | 104 | val read_lines = Bytes.read #> Bytes.trim_split_lines; | 
| 
986506233812
clarified signature: File.read_lines is based on scalable Bytes.T;
 wenzelm parents: 
75615diff
changeset | 105 | |
| 28028 | 106 | |
| 75615 | 107 | (* write *) | 
| 28028 | 108 | |
| 75615 | 109 | fun write_list path ss = File_Stream.open_output (fn stream => File_Stream.outputs stream ss) path; | 
| 110 | fun append_list path ss = File_Stream.open_append (fn stream => File_Stream.outputs stream ss) path; | |
| 16713 | 111 | |
| 112 | fun write path txt = write_list path [txt]; | |
| 113 | fun append path txt = append_list path [txt]; | |
| 6182 | 114 | |
| 28028 | 115 | |
| 56533 
cd8b6d849b6a
explicit 'document_files' in session ROOT specifications;
 wenzelm parents: 
48911diff
changeset | 116 | (* eq *) | 
| 5009 | 117 | |
| 16603 | 118 | fun eq paths = | 
| 59058 
a78612c67ec0
renamed "pairself" to "apply2", in accordance to @{apply 2};
 wenzelm parents: 
56533diff
changeset | 119 | (case try (apply2 (OS.FileSys.fileId o platform_path)) paths of | 
| 26656 | 120 | SOME ids => is_equal (OS.FileSys.compare ids) | 
| 16603 | 121 | | NONE => false); | 
| 122 | ||
| 5009 | 123 | end; |