···17 | 0, _ -> 0
18 | r, 0 -> r
19 | _, n ->
20- OpamConsole.note "retry %i: %s" (tries - n + 1) (String.concat " " cmd);
21- Unix.sleepf (Random.float 2.0); loop (n - 1)
022 in
23- loop tries
2425let run cmd =
26 let inp = Unix.open_process_in cmd in
···31let nproc () = run "nproc" |> String.trim |> int_of_string
32let mkdir dir = if not (Sys.file_exists dir) then Sys.mkdir dir 0o755
3334-let rec rm ?(recursive=false) path =
35 try
36 let stat = Unix.lstat path in
37 match stat.st_kind with
38- | S_REG | S_LNK | S_CHR | S_BLK | S_FIFO | S_SOCK ->
39- (try
40- Unix.unlink path
41- with
42- Unix.Unix_error (Unix.EACCES, _, _) ->
43- Unix.chmod path (stat.st_perm lor 0o222);
44- Unix.unlink path)
00045 | S_DIR ->
46- if recursive then
47- Sys.readdir path
48- |> Array.iter (fun f ->
49- rm ~recursive (Filename.concat path f));
50- Unix.rmdir path
51 with
52- | Unix.Unix_error (Unix.ENOENT, _, _) -> ()
5354module IntSet = Set.Make (Int)
55···93exception Copy_error of string
9495let cp ?(buffer_size = 65536) ?(preserve_permissions = true) ?(preserve_times = true) src dst =
96- let safe_close fd = try Unix.close fd with _ -> () in
00097 let src_stats =
98- try Unix.stat src
99- with Unix.Unix_error (err, _, _) ->
100- raise (Copy_error (Printf.sprintf "Cannot stat source file '%s': %s" src (Unix.error_message err)))
101 in
102- if src_stats.st_kind <> S_REG then
103- raise (Copy_error (Printf.sprintf "Source '%s' is not a regular file" src));
104 let src_fd =
105- try Unix.openfile src [O_RDONLY] 0
106- with Unix.Unix_error (err, _, _) ->
107- raise (Copy_error (Printf.sprintf "Cannot open source file '%s': %s" src (Unix.error_message err)))
108 in
109 let dst_fd =
110- try Unix.openfile dst [O_WRONLY; O_CREAT; O_TRUNC] src_stats.st_perm
111- with Unix.Unix_error (err, _, _) ->
112- safe_close src_fd;
113- raise (Copy_error (Printf.sprintf "Cannot open destination file '%s': %s" dst (Unix.error_message err)))
114 in
115 let buffer = Bytes.create buffer_size in
116 let rec copy_loop () =
117 try
118- match (Unix.read src_fd buffer 0 buffer_size) with
119 | 0 -> ()
120 | bytes_read ->
121- let rec write_all pos remaining =
122- if remaining > 0 then
123- let bytes_written = Unix.write dst_fd buffer pos remaining in
124- write_all (pos + bytes_written) (remaining - bytes_written)
125- in
126- write_all 0 bytes_read;
127- copy_loop ()
128- with Unix.Unix_error (err, _, _) ->
129- safe_close src_fd;
130- safe_close dst_fd;
131- raise (Copy_error (Printf.sprintf "Error during copy: %s" (Unix.error_message err)))
0132 in
133 copy_loop ();
134 safe_close src_fd;
135 safe_close dst_fd;
136- if preserve_permissions then begin
137- try Unix.chmod dst src_stats.st_perm
138- with Unix.Unix_error (err, _, _) ->
139- Printf.eprintf "Warning: Could not preserve permissions: %s\n" (Unix.error_message err)
140- end;
141- if preserve_times then begin
142- try Unix.utimes dst src_stats.st_atime src_stats.st_mtime
143- with Unix.Unix_error (err, _, _) ->
144- Printf.eprintf "Warning: Could not preserve timestamps: %s\n" (Unix.error_message err)
145- end
146147let hardlink_tree ~source ~target =
148 let rec process_directory current_source current_target =
149 let entries = Sys.readdir current_source in
150- Array.iter (fun entry ->
151- let source = Filename.concat current_source entry in
152- let target = Filename.concat current_target entry in
153- try
154- let stat = Unix.lstat source in
155- match stat.st_kind with
156- | Unix.S_LNK ->
157- if not (Sys.file_exists target) then
158- Unix.symlink (Unix.readlink source) target
159- | Unix.S_REG ->
160- if not (Sys.file_exists target) then
161- Unix.link source target
162- | Unix.S_DIR ->
163- mkdir target;
164- process_directory source target
165- | S_CHR | S_BLK | S_FIFO | S_SOCK ->
166- ()
167- with
168- | Unix.Unix_error (Unix.EMLINK, _, _) ->
169- cp source target
170- | Unix.Unix_error (err, _, _) ->
171- Printf.eprintf "Warning: %s -> %s = %s\n" source target (Unix.error_message err);
172- ) entries
173 in
174 process_directory source target
···17 | 0, _ -> 0
18 | r, 0 -> r
19 | _, n ->
20+ OpamConsole.note "retry %i: %s" (tries - n + 1) (String.concat " " cmd);
21+ Unix.sleepf (Random.float 2.0);
22+ loop (n - 1)
23 in
24+ loop tries
2526let run cmd =
27 let inp = Unix.open_process_in cmd in
···32let nproc () = run "nproc" |> String.trim |> int_of_string
33let mkdir dir = if not (Sys.file_exists dir) then Sys.mkdir dir 0o755
3435+let rec rm ?(recursive = false) path =
36 try
37 let stat = Unix.lstat path in
38 match stat.st_kind with
39+ | S_REG
40+ | S_LNK
41+ | S_CHR
42+ | S_BLK
43+ | S_FIFO
44+ | S_SOCK -> (
45+ try Unix.unlink path with
46+ | Unix.Unix_error (Unix.EACCES, _, _) ->
47+ Unix.chmod path (stat.st_perm lor 0o222);
48+ Unix.unlink path)
49 | S_DIR ->
50+ if recursive then Sys.readdir path |> Array.iter (fun f -> rm ~recursive (Filename.concat path f));
51+ Unix.rmdir path
00052 with
53+ | Unix.Unix_error (Unix.ENOENT, _, _) -> ()
5455module IntSet = Set.Make (Int)
56···94exception Copy_error of string
9596let cp ?(buffer_size = 65536) ?(preserve_permissions = true) ?(preserve_times = true) src dst =
97+ let safe_close fd =
98+ try Unix.close fd with
99+ | _ -> ()
100+ in
101 let src_stats =
102+ try Unix.stat src with
103+ | Unix.Unix_error (err, _, _) -> raise (Copy_error (Printf.sprintf "Cannot stat source file '%s': %s" src (Unix.error_message err)))
0104 in
105+ if src_stats.st_kind <> S_REG then raise (Copy_error (Printf.sprintf "Source '%s' is not a regular file" src));
0106 let src_fd =
107+ try Unix.openfile src [ O_RDONLY ] 0 with
108+ | Unix.Unix_error (err, _, _) -> raise (Copy_error (Printf.sprintf "Cannot open source file '%s': %s" src (Unix.error_message err)))
0109 in
110 let dst_fd =
111+ try Unix.openfile dst [ O_WRONLY; O_CREAT; O_TRUNC ] src_stats.st_perm with
112+ | Unix.Unix_error (err, _, _) ->
113+ safe_close src_fd;
114+ raise (Copy_error (Printf.sprintf "Cannot open destination file '%s': %s" dst (Unix.error_message err)))
115 in
116 let buffer = Bytes.create buffer_size in
117 let rec copy_loop () =
118 try
119+ match Unix.read src_fd buffer 0 buffer_size with
120 | 0 -> ()
121 | bytes_read ->
122+ let rec write_all pos remaining =
123+ if remaining > 0 then
124+ let bytes_written = Unix.write dst_fd buffer pos remaining in
125+ write_all (pos + bytes_written) (remaining - bytes_written)
126+ in
127+ write_all 0 bytes_read;
128+ copy_loop ()
129+ with
130+ | Unix.Unix_error (err, _, _) ->
131+ safe_close src_fd;
132+ safe_close dst_fd;
133+ raise (Copy_error (Printf.sprintf "Error during copy: %s" (Unix.error_message err)))
134 in
135 copy_loop ();
136 safe_close src_fd;
137 safe_close dst_fd;
138+ (if preserve_permissions then
139+ try Unix.chmod dst src_stats.st_perm with
140+ | Unix.Unix_error (err, _, _) -> Printf.eprintf "Warning: Could not preserve permissions: %s\n" (Unix.error_message err));
141+ if preserve_times then
142+ try Unix.utimes dst src_stats.st_atime src_stats.st_mtime with
143+ | Unix.Unix_error (err, _, _) -> Printf.eprintf "Warning: Could not preserve timestamps: %s\n" (Unix.error_message err)
0000144145let hardlink_tree ~source ~target =
146 let rec process_directory current_source current_target =
147 let entries = Sys.readdir current_source in
148+ Array.iter
149+ (fun entry ->
150+ let source = Filename.concat current_source entry in
151+ let target = Filename.concat current_target entry in
152+ try
153+ let stat = Unix.lstat source in
154+ match stat.st_kind with
155+ | S_LNK -> if not (Sys.file_exists target) then Unix.symlink (Unix.readlink source) target
156+ | S_REG -> if not (Sys.file_exists target) then Unix.link source target
157+ | S_DIR ->
158+ mkdir target;
159+ process_directory source target
160+ | S_CHR
161+ | S_BLK
162+ | S_FIFO
163+ | S_SOCK ->
164+ ()
165+ with
166+ | Unix.Unix_error (Unix.EMLINK, _, _) -> cp source target
167+ | Unix.Unix_error (err, _, _) -> Printf.eprintf "Warning: %s -> %s = %s\n" source target (Unix.error_message err))
168+ entries
00169 in
170 process_directory source target
+10
bin/s.ml
···0000000000
···1+module type CONTAINER = sig
2+ type t
3+4+ val init : config:Config.t -> t
5+ val deinit : t:t -> unit
6+ val config : t:t -> Config.t
7+ val run : t:t -> temp_dir:string -> string -> string -> unit
8+ val build : t:t -> temp_dir:string -> string -> OpamPackage.t -> OpamPackage.Set.t OpamPackage.Map.t -> OpamPackage.Set.t -> unit
9+ val std_env : string -> OpamTypes.variable_contents option
10+end
+22
bin/util.ml
···0000000000000000000000
···1+let hash_of_set s = s |> OpamPackage.Set.to_list |> List.map OpamPackage.to_string |> String.concat " " |> Digest.string |> Digest.to_hex
2+3+let std_env ?(ocaml_native = true) ?opam_version ~arch ~os ~os_distribution ~os_family ~os_version () = function
4+ | "arch" -> Some (OpamTypes.S arch)
5+ | "os" -> Some (OpamTypes.S os)
6+ | "os-distribution" -> Some (OpamTypes.S os_distribution)
7+ | "os-version" -> Some (OpamTypes.S os_version)
8+ | "os-family" -> Some (OpamTypes.S os_family)
9+ | "opam-version" -> Some (OpamVariable.S (Option.value ~default:OpamVersion.(to_string current) opam_version))
10+ (* There is no system compliler *)
11+ | "sys-ocaml-arch"
12+ | "sys-ocaml-cc"
13+ | "sys-ocaml-libc"
14+ | "sys-ocaml-system"
15+ | "sys-ocaml-version" ->
16+ Some (OpamTypes.S "")
17+ | "ocaml:native" -> Some (OpamTypes.B ocaml_native)
18+ | "ocaml:version" -> Some (OpamTypes.S "5.3.0")
19+ | "enable-ocaml-beta-repository" -> None (* Fake variable? *)
20+ | v ->
21+ OpamConsole.warning "Unknown variable %S" v;
22+ None