This repository has been archived by the owner on Jul 19, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
/
reqtraceUtil.ml
165 lines (139 loc) · 4.67 KB
/
reqtraceUtil.ml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
(*
* Copyright (c) 2015 Luke Dunstan <[email protected]>
* Copyright (c) 2014 David Sheets <[email protected]>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*)
module Error = struct
let source_missing path =
`Error (false, "source "^path^" does not exist")
let dir_to_file dir file =
`Error (false, "can't process directory "^dir^" into file "^file)
(*
let unknown_file_type path =
`Error (false, "don't know how to handle file "^path)
`Error (false, "source "^in_file^" is not a cmt")
let not_an_interface path =
`Error (false, path^" is not an interface")
let wrong_version_interface path =
`Error (false, path^" has the wrong format version")
let not_an_implementation path =
`Error (false, path^" is not an implementation")
let wrong_version_implementation path =
`Error (false, path^" has the wrong format version")
let corrupted_interface path =
`Error (false, path^" is corrupted")
let not_a_typedtree path =
`Error (false, path^" is not a typed tree")
*)
let read_cmt_failed path msg =
`Error (false, path ^ ": failed to load cmt: " ^ msg)
end
let combine_errors errs = `Error
begin List.fold_left (fun (show_help,str) -> function
| `Error (err_help,err_str) -> (err_help || show_help, str ^ "\n" ^ err_str)
) (false,"") errs
end
let map_ret f = function
| `Ok v -> `Ok (f v)
| `Error (help,msg) as err -> err
let rec read_files acc dh =
match
try Some (Unix.readdir dh)
with End_of_file -> None
with Some file -> read_files (file::acc) dh | None -> acc
let rec all_files base acc dh =
let files = read_files [] dh in
List.fold_left (fun acc -> function
| "." | ".." -> acc
| dirent ->
let file = Filename.concat base dirent in
try
let dh = Unix.opendir file in
let acc = all_files file acc dh in
Unix.closedir dh;
acc
with
| Unix.Unix_error (Unix.ENOTDIR, _, _) -> file::acc
| Unix.Unix_error (Unix.ENOENT, _, _) -> (* dangling symlink or race *)
acc
) acc files
let in_dir path f =
let cwd = Unix.getcwd () in
Unix.chdir path;
try let r = f () in Unix.chdir cwd; r
with e -> Unix.chdir cwd; raise e
let foldp_paths f p acc dir =
let dh = Unix.opendir dir in
let files = in_dir dir (fun () -> all_files "" [] dh) in
let () = Unix.closedir dh in
List.fold_left (fun acc file ->
if p file dir then f acc file else acc
) acc files
let rec ascent_of_depth tl = function
| 0 -> tl
| n -> ascent_of_depth ("../" ^ tl) (n - 1)
let depth path =
max 0 (List.length (Stringext.split path ~on:'/') - 1)
let rel_of_path depth path =
if path <> "" && path.[0] = '/'
then path
else (ascent_of_depth "" depth) ^ path
let is_link path =
let open Unix in
try
(lstat path).st_kind = S_LNK
with
| Unix.Unix_error _ -> false
let copy in_file out_file =
if is_link out_file then
`Error (false, out_file ^ " is a symbolic link")
else
let page_size = 4096 in
let ic = open_in_bin in_file in
let oc = open_out_bin out_file in
let buf = Bytes.create page_size in
let rec copy_more () =
match input ic buf 0 page_size with
| 0 -> ()
| len -> output oc buf 0 len; copy_more ()
in
copy_more ();
close_in ic;
close_out oc;
`Ok out_file
module Dir = struct
module Error = struct
let nondirectory_segment path =
`Error (false, "path "^path^" is not a directory")
end
let rec make_exist ~perm path =
try Unix.access path []; None
with
| Unix.Unix_error (Unix.ENOENT, _, _) ->
let dir = Filename.dirname path in
begin match make_exist ~perm dir with
| None ->
Unix.(mkdir path perm);
None
| Some err -> Some err
end
| Unix.Unix_error (Unix.ENOTDIR, _, _) ->
Some (Error.nondirectory_segment path)
let make_dirs_exist ~perm =
List.fold_left (fun err_opt path ->
match err_opt with None -> make_exist ~perm path | Some err -> Some err
) None
let name path = match Filename.dirname path with "." -> "" | p -> p
end