Make Dune_project.t private

To ensure we can't mutate the mutable fields and that the value is
shared, which is important for the profile_file field for instance.

To make sure we don't confuse the root field for a path in the build
directory, change its type to Path.Local.t.

Signed-off-by: Jeremie Dimino <jeremie@dimino.org>
This commit is contained in:
Jeremie Dimino 2018-06-12 10:49:39 +01:00 committed by Jérémie Dimino
parent ef77f83cec
commit f24cf5d110
7 changed files with 37 additions and 26 deletions

View File

@ -114,7 +114,7 @@ end
type t = type t =
{ kind : Kind.t { kind : Kind.t
; name : Name.t ; name : Name.t
; root : Path.t ; root : Path.Local.t
; version : string option ; version : string option
; packages : Package.t Package.Name.Map.t ; packages : Package.t Package.Name.Map.t
; mutable stanza_parser : Stanza.t list Sexp.Of_sexp.t ; mutable stanza_parser : Stanza.t list Sexp.Of_sexp.t
@ -196,12 +196,17 @@ end
let filename = "dune-project" let filename = "dune-project"
let get_local_path p =
match Path.kind p with
| External _ -> assert false
| Local p -> p
let anonymous = lazy( let anonymous = lazy(
let t = let t =
{ kind = Dune { kind = Dune
; name = Name.anonymous_root ; name = Name.anonymous_root
; packages = Package.Name.Map.empty ; packages = Package.Name.Map.empty
; root = Path.root ; root = get_local_path Path.root
; version = None ; version = None
; stanza_parser = (fun _ -> assert false) ; stanza_parser = (fun _ -> assert false)
; project_file = None ; project_file = None
@ -248,7 +253,7 @@ let parse ~dir ~lang_stanzas ~packages ~file =
let t = let t =
{ kind = Dune { kind = Dune
; name ; name
; root = dir ; root = get_local_path dir
; version ; version
; packages ; packages
; stanza_parser = (fun _ -> assert false) ; stanza_parser = (fun _ -> assert false)
@ -270,7 +275,7 @@ let make_jbuilder_project ~dir packages =
let t = let t =
{ kind = Jbuilder { kind = Jbuilder
; name = default_name ~dir ~packages ; name = default_name ~dir ~packages
; root = dir ; root = get_local_path dir
; version = None ; version = None
; packages ; packages
; stanza_parser = (fun _ -> assert false) ; stanza_parser = (fun _ -> assert false)
@ -314,7 +319,7 @@ let project_file t =
match t.project_file with match t.project_file with
| Some file -> file | Some file -> file
| None -> | None ->
let file = Path.drop_optional_build_context (Path.relative t.root filename) in let file = Path.relative (Path.of_local t.root) filename in
let maj, min = fst (Lang.latest "dune") in let maj, min = fst (Lang.latest "dune") in
let s = sprintf "(lang dune %d.%d)" maj min in let s = sprintf "(lang dune %d.%d)" maj min in
notify_user notify_user

View File

@ -30,10 +30,10 @@ module Name : sig
end end
(* CR-soon diml: make this abstract *) (* CR-soon diml: make this abstract *)
type t = type t = private
{ kind : Kind.t { kind : Kind.t
; name : Name.t ; name : Name.t
; root : Path.t ; root : Path.Local.t
; version : string option ; version : string option
; packages : Package.t Package.Name.Map.t ; packages : Package.t Package.Name.Map.t
; mutable stanza_parser : Stanza.t list Sexp.Of_sexp.t ; mutable stanza_parser : Stanza.t list Sexp.Of_sexp.t

View File

@ -214,10 +214,9 @@ let load ?extra_ignored_subtrees ?(ignore_promoted_rules=false) () =
File_tree.fold ftree ~traverse_ignored_dirs:false ~init:[] File_tree.fold ftree ~traverse_ignored_dirs:false ~init:[]
~f:(fun dir acc -> ~f:(fun dir acc ->
let p = File_tree.Dir.project dir in let p = File_tree.Dir.project dir in
if p.root = File_tree.Dir.path dir then match Path.kind (File_tree.Dir.path dir) with
p :: acc | Local d when d = p.root -> p :: acc
else | _ -> acc)
acc)
in in
let packages = let packages =
List.fold_left projects ~init:Package.Name.Map.empty List.fold_left projects ~init:Package.Name.Map.empty
@ -235,7 +234,7 @@ let load ?extra_ignored_subtrees ?(ignore_promoted_rules=false) () =
in in
let projects = let projects =
List.map projects ~f:(fun (p : Dune_project.t) -> List.map projects ~f:(fun (p : Dune_project.t) ->
(p.root, p)) (Path.of_local p.root, p))
|> Path.Map.of_list_exn |> Path.Map.of_list_exn
in in
assert (Path.Map.mem projects Path.root); assert (Path.Map.mem projects Path.root);

View File

@ -3,9 +3,10 @@ open Import
type t = type t =
{ project : Dune_project.t { project : Dune_project.t
; db : Lib.DB.t ; db : Lib.DB.t
; root : Path.t (* Path inside the build directory *)
} }
let root t = t.project.root let root t = t.root
let name t = t.project.name let name t = t.project.name
let project t = t.project let project t = t.project
let libs t = t.db let libs t = t.db
@ -58,7 +59,7 @@ module DB = struct
| Ok x -> x | Ok x -> x
| Error (_name, project1, project2) -> | Error (_name, project1, project2) ->
let to_sexp (project : Dune_project.t) = let to_sexp (project : Dune_project.t) =
Sexp.To_sexp.(pair Dune_project.Name.sexp_of_t Path.sexp_of_t) Sexp.To_sexp.(pair Dune_project.Name.sexp_of_t Path.Local.sexp_of_t)
(project.name, project.root) (project.name, project.root)
in in
Exn.code_error "Scope.DB.create got two projects with the same name" Exn.code_error "Scope.DB.create got two projects with the same name"
@ -110,6 +111,7 @@ module DB = struct
~all:(fun () -> String.Map.keys public_libs) ~all:(fun () -> String.Map.keys public_libs)
in in
let by_name = let by_name =
let build_context_dir = Path.relative Path.build_dir context in
Project_name_map.merge projects_by_name libs_by_project_name Project_name_map.merge projects_by_name libs_by_project_name
~f:(fun _name project libs -> ~f:(fun _name project libs ->
let project = Option.value_exn project in let project = Option.value_exn project in
@ -117,11 +119,12 @@ module DB = struct
let db = let db =
Lib.DB.create_from_library_stanzas libs ~parent:public_libs Lib.DB.create_from_library_stanzas libs ~parent:public_libs
in in
Some { project; db }) let root = Path.append_local build_context_dir project.root in
Some { project; db; root })
in in
by_name_cell := by_name; by_name_cell := by_name;
let by_dir = Hashtbl.create 1024 in let by_dir = Hashtbl.create 1024 in
Project_name_map.iter by_name ~f:(fun scope -> Project_name_map.iter by_name ~f:(fun scope ->
Hashtbl.add by_dir scope.project.root scope); Hashtbl.add by_dir scope.root scope);
({ by_name; by_dir; context }, public_libs) ({ by_name; by_dir; context }, public_libs)
end end

View File

@ -564,6 +564,7 @@ let make_local_path p =
match Local.Prefix.drop (Lazy.force build_dir_prefix) p with match Local.Prefix.drop (Lazy.force build_dir_prefix) p with
| None -> in_source_tree p | None -> in_source_tree p
| Some p -> in_build_dir p | Some p -> in_build_dir p
let of_local = make_local_path
let relative ?error_loc t fn = let relative ?error_loc t fn =
match fn with match fn with
@ -658,6 +659,12 @@ let is_descendant t ~of_ =
| Local t, Local of_ -> Local.is_descendant t ~of_ | Local t, Local of_ -> Local.is_descendant t ~of_
| _, _ -> false | _, _ -> false
let append_local a b =
match a with
| In_source_tree a -> in_source_tree (Local.append a b)
| In_build_dir a -> in_build_dir (Local.append a b)
| External a -> external_ (External.relative a (Local.to_string b))
let append a b = let append a b =
match kind b with match kind b with
| External _ -> | External _ ->
@ -665,12 +672,7 @@ let append a b =
[ "a", sexp_of_t a [ "a", sexp_of_t a
; "b", sexp_of_t b ; "b", sexp_of_t b
] ]
| Local b -> | Local b -> append_local a b
begin match a with
| In_source_tree a -> in_source_tree (Local.append a b)
| In_build_dir a -> in_build_dir (Local.append a b)
| External a -> external_ (External.relative a (Local.to_string b))
end
let basename t = let basename t =
match kind t with match kind t with

View File

@ -1,6 +1,7 @@
(** In the current workspace (anything under the current project root) *) (** In the current workspace (anything under the current project root) *)
module Local : sig module Local : sig
type t type t
val sexp_of_t : t -> Sexp.t
end end
(** In the outside world *) (** In the outside world *)
@ -45,6 +46,8 @@ val to_string : t -> string
(** [to_string_maybe_quoted t] is [maybe_quoted (to_string t)] *) (** [to_string_maybe_quoted t] is [maybe_quoted (to_string t)] *)
val to_string_maybe_quoted : t -> string val to_string_maybe_quoted : t -> string
val kind : t -> Kind.t
val root : t val root : t
val is_root : t -> bool val is_root : t -> bool
@ -69,6 +72,7 @@ val descendant : t -> of_:t -> t option
val is_descendant : t -> of_:t -> bool val is_descendant : t -> of_:t -> bool
val append : t -> t -> t val append : t -> t -> t
val append_local : t -> Local.t -> t
val basename : t -> string val basename : t -> string
val parent : t -> t option val parent : t -> t option
@ -147,6 +151,8 @@ val set_build_dir : Kind.t -> unit
(** paths guaranteed to be in the source directory *) (** paths guaranteed to be in the source directory *)
val in_source : string -> t val in_source : string -> t
val of_local : Local.t -> t
(** Set the workspace root. Can onyl be called once and the path must be (** Set the workspace root. Can onyl be called once and the path must be
absolute *) absolute *)
val set_root : External.t -> unit val set_root : External.t -> unit

View File

@ -216,10 +216,6 @@ let create
| _ -> None)) | _ -> None))
in in
let scopes, public_libs = let scopes, public_libs =
let projects =
List.map projects ~f:(fun (project : Dune_project.t) ->
{ project with root = Path.append context.build_dir project.root })
in
Scope.DB.create Scope.DB.create
~projects ~projects
~context:context.name ~context:context.name