<commit_before>(* Copyright (C) 2013, <NAME>
 * See the README file for details, or visit http://0install.net.
 *)

(** Getting the dependency tree from a selections document. *)

open Support.Common
open General

module U = Support.Utils

class indenter (printer : string -> unit) =
  object
    val mutable indentation = ""

    method print msg =
      printer (indentation ^ msg ^ "\n")

    method with_indent extra (fn:unit -> unit) =
      let old = indentation in
      indentation <- indentation ^ extra;
      fn ();
      indentation <- old
  end

module type MODEL = sig
  include Sigs.CORE_MODEL
  include Sigs.SELECTIONS with
    type impl := impl and
    type command_name := command_name and
    type requirements := requirements and
    type role := Role.t
end

module Make (Model : MODEL) = struct
  (** Convert selections as a dependency tree (as displayed by "0install show",
   * etc). If multiple components share a dependency, only the first one is
   * included. *)
  let as_tree result =
    let seen = ref Model.RoleMap.empty in

    let rec build_node role ~essential =
      if Model.RoleMap.mem role !seen then None
      else (
        let sel = Model.get_selected role result in

        (* We ignore optional non-selected dependencies; if another component has an
         * essential dependency on it, we'll include it then. *)
        if sel = None && not essential then (
          None
        ) else (
          seen := Model.RoleMap.add role true !seen;

          let details =
            match sel with
            | Some impl ->
                let impl_deps, _self_commands = Model.requires role impl in
                let deps = ref impl_deps in

                Model.selected_commands result role |> List.iter (fun command_name ->
                  let command = Model.get_command impl command_name
                    |? lazy (raise_safe "BUG: Missing selected command '%s'!" (command_name : Model.command_name :> string)) in
                  let command_deps, _self_commands = Model.command_requires role command in
                  deps := command_deps @ !deps
                );

                let children =
                  !deps |> U.filter_map (fun dep ->
                    let {Model.dep_role; dep_importance; dep_required_commands = _} = Model.dep_info dep in
                    if dep_importance <> `restricts then
                      build_node dep_role ~essential:(dep_importance = `essential)
                    else None
                  ) in

                `Selected (impl, children)
            | None ->
                (* Should only happen if we get a malformed selections file. *)
                log_warning "Missing essential dependency on '%s' and no problem reported!" (Model.Role.to_string role);
                `Problem in<commit_msg>Don't log a warning about incomplete solves<commit_after>(* Copyright (C) 2013, <NAME>
 * See the README file for details, or visit http://0install.net.
 *)

(** Getting the dependency tree from a selections document. *)

open Support.Common
open General

module U = Support.Utils

class indenter (printer : string -> unit) =
  object
    val mutable indentation = ""

    method print msg =
      printer (indentation ^ msg ^ "\n")

    method with_indent extra (fn:unit -> unit) =
      let old = indentation in
      indentation <- indentation ^ extra;
      fn ();
      indentation <- old
  end

module type MODEL = sig
  include Sigs.CORE_MODEL
  include Sigs.SELECTIONS with
    type impl := impl and
    type command_name := command_name and
    type requirements := requirements and
    type role := Role.t
end

module Make (Model : MODEL) = struct
  (** Convert selections as a dependency tree (as displayed by "0install show",
   * etc). If multiple components share a dependency, only the first one is
   * included. *)
  let as_tree result =
    let seen = ref Model.RoleMap.empty in

    let rec build_node role ~essential =
      if Model.RoleMap.mem role !seen then None
      else (
        let sel = Model.get_selected role result in

        (* We ignore optional non-selected dependencies; if another component has an
         * essential dependency on it, we'll include it then. *)
        if sel = None && not essential then (
          None
        ) else (
          seen := Model.RoleMap.add role true !seen;

          let details =
            match sel with
            | Some impl ->
                let impl_deps, _self_commands = Model.requires role impl in
                let deps = ref impl_deps in

                Model.selected_commands result role |> List.iter (fun command_name ->
                  let command = Model.get_command impl command_name
                    |? lazy (raise_safe "BUG: Missing selected command '%s'!" (command_name : Model.command_name :> string)) in
                  let command_deps, _self_commands = Model.command_requires role command in
                  deps := command_deps @ !deps
                );

                let children =
                  !deps |> U.filter_map (fun dep ->
                    let {Model.dep_role; dep_importance; dep_required_commands = _} = Model.dep_info dep in
                    if dep_importance <> `restricts then
                      build_node dep_role ~essential:(dep_importance = `essential)
                    else None
                  ) in

                `Selected (impl, children)
            | None ->
                (* Should only happen if we get a malformed selections file or a failed solve. *)
                (* log_warning "Missing essential dependency on '%s' and no problem reported!" (Model.Role.to_string role); *)
                `Problem in
{'fraction_non_alphanumeric': 0.07771929824561404, 'fraction_numerical': 0.002105263157894737, 'mean_word_length': 1.9989479221462387, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '631225', 'n_tokens_mistral': 1537, 'n_tokens_neox': 1435, 'n_words': 559}