Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

switch install: fix multiple compiler candidates #3884

Merged
merged 5 commits into from
Jun 26, 2019
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 50 additions & 33 deletions src/client/opamAuxCommands.ml
Original file line number Diff line number Diff line change
Expand Up @@ -492,13 +492,13 @@ let get_compatible_compiler ?repos rt dir =
(OpamStd.Format.itemize OpamPackage.to_string
(OpamPackage.Set.elements local_packages));
if OpamConsole.confirm "Do you want to create an empty switch regardless?"
then [], false
then None, false
else OpamStd.Sys.exit_because `Aborted)
else
let compilers = OpamPackage.Set.inter compilers installable in
try
[OpamSolution.eq_atom_of_package
(OpamPackage.Set.choose_one compilers)], true
Some (OpamSolution.eq_atom_of_package
(OpamPackage.Set.choose_one compilers)), true
with
| Not_found when not (OpamPackage.Set.is_empty local_packages) ->
OpamConsole.warning
Expand All @@ -508,45 +508,62 @@ let get_compatible_compiler ?repos rt dir =
OpamConsole.confirm
"Create the switch with no specific compiler selected, and attempt to \
continue?"
then [], false
then None, false
else OpamStd.Sys.exit_because `Aborted
| Failure _ | Not_found ->
(* Find a matching compiler from the default selection *)
let default_compiler =
OpamFile.Config.default_compiler gt.config
in
if default_compiler = Empty then
(OpamConsole.warning "No compiler selected"; [], false)
(OpamConsole.warning "No compiler selected"; None, false)
else
let candidates = OpamFormula.to_dnf default_compiler in
try
OpamStd.List.find_map
(fun atoms ->
let has_all compiler_packages =
List.for_all (fun at ->
OpamPackage.Set.exists (OpamFormula.check at) compiler_packages)
atoms
in
let compiler =
OpamFormula.packages_of_atoms
(Lazy.force virt_st.available_packages)
atoms
in
if not (has_all compiler) then None else
if OpamPackage.Set.is_empty local_packages then
Some (OpamSolution.eq_atoms_of_packages compiler)
else
(* fake universe with `local_packages` as base, just to check
coinstallability *)
let univ =
{ univ with u_base = local_packages; u_installed = local_packages }
in
let compiler = OpamSolver.installable_subset univ compiler in
if has_all compiler then
Some (OpamSolution.eq_atoms_of_packages compiler)
else None
)
candidates, false
let candidates =
OpamStd.List.find_map
(fun atoms ->
let has_all compiler_packages =
List.for_all (fun at ->
OpamPackage.Set.exists (OpamFormula.check at) compiler_packages)
atoms
in
let compiler =
OpamFormula.packages_of_atoms
(Lazy.force virt_st.available_packages)
atoms
in
if not (has_all compiler) then None else
if OpamPackage.Set.is_empty local_packages then
Some (OpamSolution.eq_atoms_of_packages compiler)
else
(* fake universe with `local_packages` as base, just to check
coinstallability *)
let univ =
{ univ with u_base = local_packages; u_installed = local_packages }
in
let compiler = OpamSolver.installable_subset univ compiler in
if has_all compiler then
Some (OpamSolution.eq_atoms_of_packages compiler)
else None
) candidates
in
let candidate =
candidates
|> List.map (fun (n,vc) ->
OpamPackage.create n
(match vc with
| Some (`Eq, v) -> v
(* all atoms are from [OpamFormula.eq_atoms_of_packages] *)
| _ -> assert false))
|> OpamPackage.Set.of_list
|> (fun s ->
OpamPackage.(max_version s
(names_of_packages s
|> Name.Set.choose)))
|> fun p -> Some (OpamSolution.eq_atom_of_package p)
in
candidate,false
with Not_found ->
OpamConsole.warning
"The default compiler selection: %s\n\
Expand All @@ -558,5 +575,5 @@ let get_compatible_compiler ?repos rt dir =
if OpamConsole.confirm
"You may also proceed, with no specific compiler selected. \
Do you want to?"
then [], false
then None, false
else OpamStd.Sys.exit_because `Aborted
2 changes: 1 addition & 1 deletion src/client/opamAuxCommands.mli
Original file line number Diff line number Diff line change
Expand Up @@ -91,4 +91,4 @@ val simulate_autopin:
warning, and returns the empty list after user confirmation. *)
val get_compatible_compiler:
?repos:repository_name list ->
'a repos_state -> dirname -> atom list * bool
'a repos_state -> dirname -> atom option * bool
22 changes: 14 additions & 8 deletions src/client/opamCommands.ml
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,7 @@ let init =
| Some comp when String.length comp <> 0->
let packages =
OpamSwitchCommand.guess_compiler_package rt comp
|> OpamStd.Option.map_default (fun x -> [x]) []
in
OpamConsole.header_msg "Creating initial switch (%s)"
(OpamFormula.string_of_atoms packages);
Expand Down Expand Up @@ -2083,19 +2084,24 @@ let switch =
| packages, _ -> packages
in
let compiler_packages rt ?repos switch compiler_opt =
let open OpamStd.Option.Op in
let single_lst p = (p >>| (fun x -> [x])) +! [] in
rjbou marked this conversation as resolved.
Show resolved Hide resolved
match packages, compiler_opt, OpamSwitch.is_external switch with
| None, None, false ->
OpamSwitchCommand.guess_compiler_package ?repos rt
(OpamSwitch.to_string switch), false
(OpamSwitch.to_string switch)
|> single_lst, false
| None, None, true ->
OpamAuxCommands.get_compatible_compiler ?repos rt
(OpamFilename.dirname_dir
(OpamSwitch.get_root rt.repos_global.root switch))
let p, local =
OpamAuxCommands.get_compatible_compiler ?repos rt
(OpamFilename.dirname_dir
(OpamSwitch.get_root rt.repos_global.root switch))
in
single_lst p, local
| _ ->
OpamStd.Option.Op.(
((compiler_opt >>|
OpamSwitchCommand.guess_compiler_package ?repos rt) +! []) @
packages +! []), false
((compiler_opt >>=
OpamSwitchCommand.guess_compiler_package ?repos rt) |> single_lst)
@ packages +! [], false
in
let param_compiler = function
| [] -> None
Expand Down
2 changes: 1 addition & 1 deletion src/client/opamSolution.mli
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ val check_solution:
(** Return an atom with a strict version constraint *)
val eq_atom: name -> version -> atom

(** Return a simple atom, with no version constrain, from a package*)
(** Return a simple atom, with no version constraint, from a package*)
val atom_of_package: package -> atom

(** Returns an atom with a strict version constraint from a package *)
Expand Down
8 changes: 4 additions & 4 deletions src/client/opamSwitchCommand.ml
Original file line number Diff line number Diff line change
Expand Up @@ -665,7 +665,7 @@ let guess_compiler_package ?repos rt name =
in
match OpamPackage.of_string_opt name with
| Some nv when OpamPackage.Set.mem nv compiler_packages ->
[OpamSolution.eq_atom_of_package nv]
Some (OpamSolution.eq_atom_of_package nv)
| Some nv when OpamRepositoryState.find_package_opt rt repos nv <> None ->
advise_compiler_dependencies rt opams compiler_packages name
[OpamSolution.eq_atom_of_package nv];
Expand All @@ -677,7 +677,7 @@ let guess_compiler_package ?repos rt name =
in
match pkgname with
| Some pkgname when OpamPackage.has_name compiler_packages pkgname ->
[pkgname, None]
Some (pkgname, None)
| Some pkgname when
OpamPackage.Map.exists (fun nv _ -> OpamPackage.name nv = pkgname) opams
->
Expand All @@ -691,8 +691,8 @@ let guess_compiler_package ?repos rt name =
compiler_packages
in
try
[OpamSolution.eq_atom_of_package
(OpamPackage.Set.choose_one has_version)]
Some (OpamSolution.eq_atom_of_package
(OpamPackage.Set.choose_one has_version))
with
| Not_found -> no_compiler_error ()
| Failure _ ->
Expand Down
2 changes: 1 addition & 1 deletion src/client/opamSwitchCommand.mli
Original file line number Diff line number Diff line change
Expand Up @@ -72,4 +72,4 @@ val get_compiler_packages:
match [name] against "pkg.version", "pkg", and, as a last resort,
"version" (for compat with older opams, eg. 'opam switch 4.02.3') *)
val guess_compiler_package:
?repos:repository_name list -> 'a repos_state -> string -> atom list
?repos:repository_name list -> 'a repos_state -> string -> atom option