diff --git a/src/client/opamAuxCommands.ml b/src/client/opamAuxCommands.ml index 6002864c0bf..3294f9e4dd1 100644 --- a/src/client/opamAuxCommands.ml +++ b/src/client/opamAuxCommands.ml @@ -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 @@ -508,7 +508,7 @@ 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 *) @@ -516,37 +516,54 @@ let get_compatible_compiler ?repos rt dir = 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\ @@ -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 diff --git a/src/client/opamAuxCommands.mli b/src/client/opamAuxCommands.mli index 570809bb5f1..0ad7352d88a 100644 --- a/src/client/opamAuxCommands.mli +++ b/src/client/opamAuxCommands.mli @@ -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 diff --git a/src/client/opamCommands.ml b/src/client/opamCommands.ml index e08a1f999b7..8c99f793a1a 100644 --- a/src/client/opamCommands.ml +++ b/src/client/opamCommands.ml @@ -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); @@ -2085,17 +2086,22 @@ let switch = let compiler_packages rt ?repos switch compiler_opt = match packages, compiler_opt, OpamSwitch.is_external switch with | None, None, false -> - OpamSwitchCommand.guess_compiler_package ?repos rt - (OpamSwitch.to_string switch), false + OpamStd.Option.to_list + (OpamSwitchCommand.guess_compiler_package ?repos rt + (OpamSwitch.to_string switch)), 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 + OpamStd.Option.to_list p, local | _ -> - OpamStd.Option.Op.( - ((compiler_opt >>| - OpamSwitchCommand.guess_compiler_package ?repos rt) +! []) @ - packages +! []), false + let open OpamStd.Option.Op in + (OpamStd.Option.to_list + (compiler_opt >>= + OpamSwitchCommand.guess_compiler_package ?repos rt)) + @ packages +! [], false in let param_compiler = function | [] -> None diff --git a/src/client/opamSolution.mli b/src/client/opamSolution.mli index fc6c1424591..528ad241b19 100644 --- a/src/client/opamSolution.mli +++ b/src/client/opamSolution.mli @@ -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 *) diff --git a/src/client/opamSwitchCommand.ml b/src/client/opamSwitchCommand.ml index bba7abadeeb..731737930c8 100644 --- a/src/client/opamSwitchCommand.ml +++ b/src/client/opamSwitchCommand.ml @@ -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]; @@ -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 -> @@ -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 _ -> diff --git a/src/client/opamSwitchCommand.mli b/src/client/opamSwitchCommand.mli index cfd910f6b22..17a510a12b6 100644 --- a/src/client/opamSwitchCommand.mli +++ b/src/client/opamSwitchCommand.mli @@ -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 diff --git a/src/core/opamStd.ml b/src/core/opamStd.ml index 8b45886e58f..7993189f16e 100644 --- a/src/core/opamStd.ml +++ b/src/core/opamStd.ml @@ -407,6 +407,10 @@ module Option = struct | Some x -> f x | None -> none + let to_list = function + | None -> [] + | Some x -> [x] + let some x = Some x let none _ = None diff --git a/src/core/opamStd.mli b/src/core/opamStd.mli index 6bdb9504645..c662b823654 100644 --- a/src/core/opamStd.mli +++ b/src/core/opamStd.mli @@ -139,6 +139,8 @@ module Option: sig val to_string: ?none:string -> ('a -> string) -> 'a option -> string + val to_list: 'a option -> 'a list + val some: 'a -> 'a option val none: 'a -> 'b option