Merge branch 'master' into subsystem-versioned

This commit is contained in:
Rudi Grinberg 2018-07-03 16:49:05 +07:00 committed by GitHub
commit 7a91a2b23b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 354 additions and 93 deletions

View File

@ -106,6 +106,8 @@ next
- Add `%{profile}` variable. (#938, @rgrinberg) - Add `%{profile}` variable. (#938, @rgrinberg)
- Do not require opam-installer anymore (#941, @diml)
1.0+beta20 (10/04/2018) 1.0+beta20 (10/04/2018)
----------------------- -----------------------

View File

@ -1053,16 +1053,6 @@ let rules =
& Arg.info [] ~docv:"TARGET")) & Arg.info [] ~docv:"TARGET"))
, Term.info "rules" ~doc ~man) , Term.info "rules" ~doc ~man)
let opam_installer () =
match Bin.which "opam-installer" with
| None ->
die "\
Sorry, you need the opam-installer tool to be able to install or
uninstall packages.
I couldn't find the opam-installer binary :-("
| Some fn -> fn
let get_prefix context ~from_command_line = let get_prefix context ~from_command_line =
match from_command_line with match from_command_line with
| Some p -> Fiber.return (Path.of_string p) | Some p -> Fiber.return (Path.of_string p)
@ -1073,6 +1063,16 @@ let get_libdir context ~libdir_from_command_line =
| Some p -> Fiber.return (Some (Path.of_string p)) | Some p -> Fiber.return (Some (Path.of_string p))
| None -> Context.install_ocaml_libdir context | None -> Context.install_ocaml_libdir context
let print_unix_error f =
try
f ()
with Unix.Unix_error (e, _, _) ->
Format.eprintf "@{<error>Error@}: %s@."
(Unix.error_message e)
let set_executable_bits x = x lor 0o111
let clear_executable_bits x = x land (lnot 0o111)
let install_uninstall ~what = let install_uninstall ~what =
let doc = let doc =
sprintf "%s packages using opam-installer." (String.capitalize what) sprintf "%s packages using opam-installer." (String.capitalize what)
@ -1080,7 +1080,6 @@ let install_uninstall ~what =
let name_ = Arg.info [] ~docv:"PACKAGE" in let name_ = Arg.info [] ~docv:"PACKAGE" in
let go common prefix_from_command_line libdir_from_command_line pkgs = let go common prefix_from_command_line libdir_from_command_line pkgs =
set_common common ~targets:[]; set_common common ~targets:[];
let opam_installer = opam_installer () in
let log = Log.create common in let log = Log.create common in
Scheduler.go ~log ~common Scheduler.go ~log ~common
(Main.setup ~log common >>= fun setup -> (Main.setup ~log common >>= fun setup ->
@ -1095,7 +1094,7 @@ let install_uninstall ~what =
List.map setup.contexts ~f:(fun ctx -> List.map setup.contexts ~f:(fun ctx ->
let fn = Path.append ctx.Context.build_dir fn in let fn = Path.append ctx.Context.build_dir fn in
if Path.exists fn then if Path.exists fn then
Left (ctx, fn) Left (ctx, (pkg, fn))
else else
Right fn)) Right fn))
|> List.partition_map ~f:(fun x -> x) |> List.partition_map ~f:(fun x -> x)
@ -1121,23 +1120,57 @@ let install_uninstall ~what =
in in
Fiber.parallel_iter install_files_by_context Fiber.parallel_iter install_files_by_context
~f:(fun (context, install_files) -> ~f:(fun (context, install_files) ->
let install_files_set = Path.Set.of_list install_files in
get_prefix context ~from_command_line:prefix_from_command_line get_prefix context ~from_command_line:prefix_from_command_line
>>= fun prefix -> >>= fun prefix ->
get_libdir context ~libdir_from_command_line get_libdir context ~libdir_from_command_line
>>= fun libdir -> >>| fun libdir ->
Fiber.parallel_iter install_files ~f:(fun path -> List.iter install_files ~f:(fun (package, path) ->
let purpose = Process.Build_job install_files_set in let entries = Install.load_install_file path in
Process.run ~purpose ~env:setup.env Strict opam_installer let paths =
([ sprintf "-%c" what.[0] Install.Section.Paths.make
; Path.to_string path ~package
; "--prefix" ~destdir:prefix
; Path.to_string prefix ?libdir
] @ ()
match libdir with in
| None -> [] let files_deleted_in = ref Path.Set.empty in
| Some p -> [ "--libdir"; Path.to_string p ] List.iter entries ~f:(fun { Install.Entry. src; dst; section } ->
)))) let src = src in
let dst = Option.value dst ~default:(Path.basename src) in
let dst =
Path.relative (Install.Section.Paths.get paths section) dst
in
let dir = Path.parent_exn dst in
if what = "install" then begin
Printf.eprintf "Installing %s\n%!"
(Path.to_string_maybe_quoted dst);
Path.mkdir_p dir;
Io.copy_file () ~src ~dst
~chmod:(
if Install.Section.should_set_executable_bit section then
set_executable_bits
else
clear_executable_bits)
end else begin
if Path.exists dst then begin
Printf.eprintf "Deleting %s\n%!"
(Path.to_string_maybe_quoted dst);
print_unix_error (fun () -> Path.unlink dst)
end;
files_deleted_in := Path.Set.add !files_deleted_in dir;
end;
Path.Set.to_list !files_deleted_in
(* This [List.rev] is to ensure we process children
directories before their parents *)
|> List.rev
|> List.iter ~f:(fun dir ->
if Path.exists dir then
match Path.readdir_unsorted dir with
| [] ->
Printf.eprintf "Deleting empty directory %s\n%!"
(Path.to_string_maybe_quoted dst);
print_unix_error (fun () -> Path.rmdir dir)
| _ -> ())))))
in in
( Term.(const go ( Term.(const go
$ common $ common

View File

@ -637,7 +637,7 @@ module Promotion = struct
Format.eprintf "Promoting %s to %s.@." Format.eprintf "Promoting %s to %s.@."
(Path.to_string_maybe_quoted src) (Path.to_string_maybe_quoted src)
(Path.to_string_maybe_quoted dst); (Path.to_string_maybe_quoted dst);
Io.copy_file ~src ~dst Io.copy_file ~src ~dst ()
end end
module P = Utils.Persistent(struct module P = Utils.Persistent(struct
@ -785,11 +785,11 @@ let rec exec t ~ectx ~dir ~env ~stdout_to ~stderr_to =
Io.copy_channels ic oc); Io.copy_channels ic oc);
Fiber.return () Fiber.return ()
| Copy (src, dst) -> | Copy (src, dst) ->
Io.copy_file ~src ~dst; Io.copy_file ~src ~dst ();
Fiber.return () Fiber.return ()
| Symlink (src, dst) -> | Symlink (src, dst) ->
if Sys.win32 then if Sys.win32 then
Io.copy_file ~src ~dst Io.copy_file ~src ~dst ()
else begin else begin
let src = let src =
match Path.parent dst with match Path.parent dst with

View File

@ -826,7 +826,7 @@ let rec compile_rule t ?(copy_source=false) pre_rule =
Utils.Cached_digest.file in_source_tree) then begin Utils.Cached_digest.file in_source_tree) then begin
if mode = Promote_but_delete_on_clean then if mode = Promote_but_delete_on_clean then
Promoted_to_delete.add in_source_tree; Promoted_to_delete.add in_source_tree;
Io.copy_file ~src:path ~dst:in_source_tree Io.copy_file ~src:path ~dst:in_source_tree ()
end) end)
end; end;
t.hook Rule_completed t.hook Rule_completed

View File

@ -31,6 +31,21 @@ module Section = struct
| Man -> "man" | Man -> "man"
| Misc -> "misc" | Misc -> "misc"
let of_string = function
| "lib" -> Some Lib
| "libexec" -> Some Libexec
| "bin" -> Some Bin
| "sbin" -> Some Sbin
| "toplevel" -> Some Toplevel
| "share" -> Some Share
| "share_root" -> Some Share_root
| "etc" -> Some Etc
| "doc" -> Some Doc
| "stublibs" -> Some Stublibs
| "man" -> Some Man
| "misc" -> Some Misc
| _ -> None
let t = let t =
let open Sexp.Of_sexp in let open Sexp.Of_sexp in
enum enum
@ -48,35 +63,65 @@ module Section = struct
; "misc" , Misc ; "misc" , Misc
] ]
module Paths = struct let should_set_executable_bit = function
let lib = Path.in_source "lib" | Lib -> false
let libexec = Path.in_source "lib" | Libexec -> true
let bin = Path.in_source "bin" | Bin -> true
let sbin = Path.in_source "sbin" | Sbin -> true
let toplevel = Path.in_source "lib/toplevel" | Toplevel -> false
let share = Path.in_source "share" | Share -> false
let share_root = Path.in_source "share_root" | Share_root -> false
let etc = Path.in_source "etc" | Etc -> false
let doc = Path.in_source "doc" | Doc -> false
let stublibs = Path.in_source "lib/stublibs" | Stublibs -> true
let man = Path.in_source "man" | Man -> false
end | Misc -> false
let install_dir t ~(package : Package.Name.t) = module Paths = struct
let package = Package.Name.to_string package in type t =
match t with { lib : Path.t
| Bin -> Paths.bin ; libexec : Path.t
| Sbin -> Paths.sbin ; bin : Path.t
| Toplevel -> Paths.toplevel ; sbin : Path.t
| Share_root -> Paths.share_root ; toplevel : Path.t
| Stublibs -> Paths.stublibs ; share : Path.t
| Man -> Paths.man ; share_root : Path.t
| Lib -> Path.relative Paths.lib package ; etc : Path.t
| Libexec -> Path.relative Paths.libexec package ; doc : Path.t
| Share -> Path.relative Paths.share package ; stublibs : Path.t
| Etc -> Path.relative Paths.etc package ; man : Path.t
| Doc -> Path.relative Paths.doc package }
| Misc -> invalid_arg "Install.Section.install_dir"
let make ~package ~destdir ?(libdir=Path.relative destdir "lib") () =
let package = Package.Name.to_string package in
{ bin = Path.relative destdir "bin"
; sbin = Path.relative destdir "sbin"
; toplevel = Path.relative libdir "toplevel"
; share_root = Path.relative libdir "share"
; stublibs = Path.relative libdir "lib/stublibs"
; man = Path.relative destdir "man"
; lib = Path.relative libdir package
; libexec = Path.relative libdir package
; share = Path.relative destdir ("share/" ^ package)
; etc = Path.relative destdir ("etc/" ^ package)
; doc = Path.relative destdir ("doc/" ^ package)
}
let get t section =
match section with
| Lib -> t.lib
| Libexec -> t.libexec
| Bin -> t.bin
| Sbin -> t.sbin
| Toplevel -> t.toplevel
| Share -> t.share
| Share_root -> t.share_root
| Etc -> t.etc
| Doc -> t.doc
| Stublibs -> t.stublibs
| Man -> t.man
| Misc -> invalid_arg "Install.Paths.get"
end
end end
module Entry = struct module Entry = struct
@ -112,8 +157,8 @@ module Entry = struct
let set_src t src = { t with src } let set_src t src = { t with src }
let relative_installed_path t ~package = let relative_installed_path t ~paths =
let main_dir = Section.install_dir t.section ~package in let main_dir = Section.Paths.get paths t.section in
let dst = let dst =
match t.dst with match t.dst with
| Some x -> x | Some x -> x
@ -129,15 +174,14 @@ module Entry = struct
in in
Path.relative main_dir dst Path.relative main_dir dst
let add_install_prefix t ~package ~prefix = let add_install_prefix t ~paths ~prefix =
let opam_will_install_in_this_dir = let opam_will_install_in_this_dir = Section.Paths.get paths t.section in
Section.install_dir t.section ~package
in
let i_want_to_install_the_file_as = let i_want_to_install_the_file_as =
Path.append prefix (relative_installed_path t ~package) Path.append prefix (relative_installed_path t ~paths)
in in
let dst = let dst =
Path.reach i_want_to_install_the_file_as ~from:opam_will_install_in_this_dir Path.reach i_want_to_install_the_file_as
~from:opam_will_install_in_this_dir
in in
{ t with dst = Some dst } { t with dst = Some dst }
end end
@ -165,3 +209,62 @@ let gen_install_file entries =
| Some dst -> pr " %S {%S}" src dst); | Some dst -> pr " %S {%S}" src dst);
pr "]"); pr "]");
Buffer.contents buf Buffer.contents buf
let pos_of_opam_value : OpamParserTypes.value -> OpamParserTypes.pos = function
| Bool (pos, _) -> pos
| Int (pos, _) -> pos
| String (pos, _) -> pos
| Relop (pos, _, _, _) -> pos
| Prefix_relop (pos, _, _) -> pos
| Logop (pos, _, _, _) -> pos
| Pfxop (pos, _, _) -> pos
| Ident (pos, _) -> pos
| List (pos, _) -> pos
| Group (pos, _) -> pos
| Option (pos, _, _) -> pos
| Env_binding (pos, _, _, _) -> pos
let load_install_file path =
let open OpamParserTypes in
let file = Opam_file.load path in
let fail (fname, line, col) fmt =
let pos : Lexing.position =
{ pos_fname = fname
; pos_lnum = line
; pos_bol = 0
; pos_cnum = col
}
in
Loc.fail { start = pos; stop = pos } fmt
in
List.concat_map file.file_contents ~f:(function
| Variable (pos, section, files) -> begin
match Section.of_string section with
| None -> fail pos "Unknown install section"
| Some section -> begin
match files with
| List (_, l) ->
List.map l ~f:(function
| String (_, src) ->
{ Entry.
src = Path.of_string src
; dst = None
; section
}
| Option (_, String (_, src),
[String (_, dst)]) ->
{ Entry.
src = Path.of_string src
; dst = Some dst
; section
}
| v ->
fail (pos_of_opam_value v)
"Invalid value in .install file")
| v ->
fail (pos_of_opam_value v)
"Invalid value for install section"
end
end
| Section (pos, _) ->
fail pos "Sections are not allowed in .install file")

View File

@ -18,6 +18,37 @@ module Section : sig
| Misc | Misc
val t : t Sexp.Of_sexp.t val t : t Sexp.Of_sexp.t
(** [true] iff the executable bit should be set for files installed
in this location. *)
val should_set_executable_bit : t -> bool
module Paths : sig
type section = t
type t =
{ lib : Path.t
; libexec : Path.t
; bin : Path.t
; sbin : Path.t
; toplevel : Path.t
; share : Path.t
; share_root : Path.t
; etc : Path.t
; doc : Path.t
; stublibs : Path.t
; man : Path.t
}
val make
: package:Package.Name.t
-> destdir:Path.t
-> ?libdir:Path.t
-> unit
-> t
val get : t -> section -> Path.t
end with type section := t
end end
module Entry : sig module Entry : sig
@ -30,9 +61,11 @@ module Entry : sig
val make : Section.t -> ?dst:string -> Path.t -> t val make : Section.t -> ?dst:string -> Path.t -> t
val set_src : t -> Path.t -> t val set_src : t -> Path.t -> t
val relative_installed_path : t -> package:Package.Name.t -> Path.t val relative_installed_path : t -> paths:Section.Paths.t -> Path.t
val add_install_prefix : t -> package:Package.Name.t -> prefix:Path.t -> t val add_install_prefix : t -> paths:Section.Paths.t -> prefix:Path.t -> t
end end
val files : Entry.t list -> Path.Set.t val files : Entry.t list -> Path.Set.t
val gen_install_file : Entry.t list -> string val gen_install_file : Entry.t list -> string
val load_install_file : Path.t -> Entry.t list

View File

@ -219,12 +219,13 @@ module Gen(P : Install_params) = struct
List.exists [ "README"; "LICENSE"; "CHANGE"; "HISTORY"] List.exists [ "README"; "LICENSE"; "CHANGE"; "HISTORY"]
~f:(fun prefix -> String.is_prefix fn ~prefix) ~f:(fun prefix -> String.is_prefix fn ~prefix)
let local_install_rules (entries : Install.Entry.t list) ~package = let local_install_rules (entries : Install.Entry.t list)
~install_paths ~package =
let install_dir = Config.local_install_dir ~context:ctx.name in let install_dir = Config.local_install_dir ~context:ctx.name in
List.map entries ~f:(fun entry -> List.map entries ~f:(fun entry ->
let dst = let dst =
Path.append install_dir Path.append install_dir
(Install.Entry.relative_installed_path entry ~package) (Install.Entry.relative_installed_path entry ~paths:install_paths)
in in
Build_system.set_package (SC.build_system sctx) entry.src package; Build_system.set_package (SC.build_system sctx) entry.src package;
SC.add_rule sctx (Build.symlink ~src:entry.src ~dst); SC.add_rule sctx (Build.symlink ~src:entry.src ~dst);
@ -258,7 +259,10 @@ module Gen(P : Install_params) = struct
Path.relative (Path.append ctx.build_dir package_path) Path.relative (Path.append ctx.build_dir package_path)
(Utils.install_file ~package ~findlib_toolchain:ctx.findlib_toolchain) (Utils.install_file ~package ~findlib_toolchain:ctx.findlib_toolchain)
in in
let entries = local_install_rules entries ~package in let install_paths =
Install.Section.Paths.make ~package ~destdir:Path.root ()
in
let entries = local_install_rules entries ~package ~install_paths in
let files = Install.files entries in let files = Install.files entries in
SC.add_alias_deps sctx SC.add_alias_deps sctx
(Alias.package_install ~context:ctx ~pkg:package) (Alias.package_install ~context:ctx ~pkg:package)
@ -287,7 +291,8 @@ module Gen(P : Install_params) = struct
| Some toolchain -> | Some toolchain ->
let prefix = Path.of_string (toolchain ^ "-sysroot") in let prefix = Path.of_string (toolchain ^ "-sysroot") in
List.map entries List.map entries
~f:(Install.Entry.add_install_prefix ~prefix ~package) ~f:(Install.Entry.add_install_prefix
~paths:install_paths ~prefix)
in in
Install.gen_install_file entries) Install.gen_install_file entries)
>>> >>>

View File

@ -1132,7 +1132,9 @@ module Rule = struct
field "deps" (list Dep_conf.t) ~default:[] >>= fun deps -> field "deps" (list Dep_conf.t) ~default:[] >>= fun deps ->
field "locks" (list String_with_vars.t) ~default:[] >>= fun locks -> field "locks" (list String_with_vars.t) ~default:[] >>= fun locks ->
map_validate map_validate
(field_b "fallback" >>= fun fallback -> (field_b
~check:(Syntax.renamed_in Stanza.syntax (1, 0) ~to_:"(mode fallback)")
"fallback" >>= fun fallback ->
field_o "mode" Mode.t >>= fun mode -> field_o "mode" Mode.t >>= fun mode ->
return (fallback, mode)) return (fallback, mode))
~f:(function ~f:(function

View File

@ -66,9 +66,9 @@ let copy_channels =
in in
loop loop
let copy_file ~src ~dst = let copy_file ?(chmod=fun x -> x) ~src ~dst () =
with_file_in src ~f:(fun ic -> with_file_in src ~f:(fun ic ->
let perm = (Unix.fstat (Unix.descr_of_in_channel ic)).st_perm in let perm = (Unix.fstat (Unix.descr_of_in_channel ic)).st_perm |> chmod in
Exn.protectx (P.open_out_gen Exn.protectx (P.open_out_gen
[Open_wronly; Open_creat; Open_trunc; Open_binary] [Open_wronly; Open_creat; Open_trunc; Open_binary]
perm perm

View File

@ -23,7 +23,7 @@ val write_lines : Path.t -> string list -> unit
val copy_channels : in_channel -> out_channel -> unit val copy_channels : in_channel -> out_channel -> unit
val copy_file : src:Path.t -> dst:Path.t -> unit val copy_file : ?chmod:(int -> int) -> src:Path.t -> dst:Path.t -> unit -> unit
val read_all : in_channel -> string val read_all : in_channel -> string

View File

@ -874,9 +874,7 @@ let rm_rf =
| _ -> loop fn | _ -> loop fn
let mkdir_p = function let mkdir_p = function
| External s -> | External s -> External.mkdir_p s
Exn.code_error "Path.mkdir_p cannot create external path"
["s", External.sexp_of_t s]
| In_source_tree s -> | In_source_tree s ->
Exn.code_error "Path.mkdir_p cannot dir in source" Exn.code_error "Path.mkdir_p cannot dir in source"
["s", Local.sexp_of_t s] ["s", Local.sexp_of_t s]

View File

@ -481,9 +481,10 @@ module Of_sexp = struct
| None -> | None ->
(None, add_known name state) (None, add_known name state)
let field_b name = let field_b ?check name =
field name ~default:false field name ~default:false
(eos >>= function (Option.value check ~default:(return ()) >>= fun () ->
eos >>= function
| true -> return true | true -> return true
| _ -> bool) | _ -> bool)

View File

@ -216,7 +216,7 @@ module Of_sexp : sig
-> 'a t -> 'a t
-> 'a option fields_parser -> 'a option fields_parser
val field_b : string -> bool fields_parser val field_b : ?check:(unit t) -> string -> bool fields_parser
(** A field that can appear multiple times *) (** A field that can appear multiple times *)
val multi_field val multi_field

View File

@ -124,7 +124,7 @@ let renamed_in t ver ~to_ =
else begin else begin
desc () >>= fun (loc, what) -> desc () >>= fun (loc, what) ->
Loc.fail loc Loc.fail loc
"%s was renamed to '%s' in %s of %s" what to_ "%s was renamed to '%s' in the %s version of %s" what to_
(Version.to_string ver) t.desc (Version.to_string ver) t.desc
end end

View File

@ -128,6 +128,14 @@
test-cases/exec-cmd test-cases/exec-cmd
(progn (run %{exe:cram.exe} -test run.t) (diff? run.t run.t.corrected))))) (progn (run %{exe:cram.exe} -test run.t) (diff? run.t run.t.corrected)))))
(alias
(name fallback-dune)
(deps (package dune) (source_tree test-cases/fallback-dune))
(action
(chdir
test-cases/fallback-dune
(progn (run %{exe:cram.exe} -test run.t) (diff? run.t run.t.corrected)))))
(alias (alias
(name findlib) (name findlib)
(deps (package dune) (source_tree test-cases/findlib)) (deps (package dune) (source_tree test-cases/findlib))
@ -606,6 +614,7 @@
(alias env) (alias env)
(alias exclude-missing-module) (alias exclude-missing-module)
(alias exec-cmd) (alias exec-cmd)
(alias fallback-dune)
(alias findlib) (alias findlib)
(alias findlib-error) (alias findlib-error)
(alias force-test) (alias force-test)
@ -678,6 +687,7 @@
(alias env) (alias env)
(alias exclude-missing-module) (alias exclude-missing-module)
(alias exec-cmd) (alias exec-cmd)
(alias fallback-dune)
(alias findlib) (alias findlib)
(alias findlib-error) (alias findlib-error)
(alias force-test) (alias force-test)

View File

@ -0,0 +1,4 @@
(rule
(fallback)
(targets)
(action (with-stdout-to foo.txt (echo "testing"))))

View File

@ -0,0 +1,4 @@
(rule
(fallback false)
(targets)
(action (with-stdout-to foo.txt (echo "testing"))))

View File

@ -0,0 +1,5 @@
(rule
((fallback)
(targets (foo.txt))
(action (with-stdout-to foo.txt (echo "testing")))))

View File

@ -0,0 +1,20 @@
fallback isn't allowed in dune
$ dune build --root dune1
Info: creating file dune-project with this contents: (lang dune 1.0)
File "dune", line 2, characters 1-11:
Error: 'fallback' was renamed to '(mode fallback)' in the 1.0 version of the dune language
[1]
2nd fallback form isn't allowed either
$ dune build --root dune2
Info: creating file dune-project with this contents: (lang dune 1.0)
File "dune", line 2, characters 1-17:
Error: 'fallback' was renamed to '(mode fallback)' in the 1.0 version of the dune language
[1]
But it is allowed in jbuilder
$ jbuilder build --root jbuild
Entering directory 'jbuild'

View File

@ -1,13 +1,54 @@
(**************************************************************************)
(* *)
(* Copyright 2012-2015 OCamlPro *)
(* Copyright 2012 INRIA *)
(* *)
(* All rights reserved. This file is distributed under the terms of the *)
(* GNU Lesser General Public License version 2.1, with the special *)
(* exception on linking described in the file LICENSE. *)
(* *)
(**************************************************************************)
type relop = [ `Eq | `Neq | `Geq | `Gt | `Leq | `Lt ]
type logop = [ `And | `Or ]
type pfxop = [ `Not ]
type file_name = string
(** Source file positions: filename, line, column *)
type pos = file_name * int * int
type env_update_op = Eq | PlusEq | EqPlus | ColonEq | EqColon | EqPlusEq
(** Base values *)
type value = type value =
| String of unit * string | Bool of pos * bool
| List of unit * value list | Int of pos * int
| Other | String of pos * string
| Relop of pos * relop * value * value
| Prefix_relop of pos * relop * value
| Logop of pos * logop * value * value
| Pfxop of pos * pfxop * value
| Ident of pos * string
| List of pos * value list
| Group of pos * value list
| Option of pos * value * value list
| Env_binding of pos * value * env_update_op * value
type opamfile_item = (** An opamfile section *)
| Variable of unit * string * value type opamfile_section = {
| Other section_kind : string;
section_name : string option;
section_items : opamfile_item list;
}
type opamfile = (** An opamfile is composed of sections and variable definitions *)
{ file_contents : opamfile_item list and opamfile_item =
; file_name : string | Section of pos * opamfile_section
} | Variable of pos * string * value
(** A file is a list of items and the filename *)
type opamfile = {
file_contents: opamfile_item list;
file_name : file_name;
}