File: print-stats.ml

package info (click to toggle)
botch 0.24-6.1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,084,624 kB
  • sloc: xml: 11,924,892; ml: 4,489; python: 3,890; sh: 1,268; makefile: 334
file content (207 lines) | stat: -rw-r--r-- 10,126 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
(**************************************************************************)
(*                                                                        *)
(*  Copyright (C) 2012 Johannes 'josch' Schauer <j.schauer@email.de>      *)
(*  Copyright (C) 2012 Pietro Abate <pietro.abate@pps.jussieu.fr>         *)
(*                                                                        *)
(*  This library is free software: you can redistribute it and/or modify  *)
(*  it under the terms of the GNU Lesser General Public License as        *)
(*  published by the Free Software Foundation, either version 3 of the    *)
(*  License, or (at your option) any later version.  A special linking    *)
(*  exception to the GNU Lesser General Public License applies to this    *)
(*  library, see the COPYING file for more information.                   *)
(**************************************************************************)

open! ExtLib
open Datatypes_t
open Dose_common
open Dose_debian
open Dose_doseparse

#define __label __FILE__
let label =  __label ;;
include Util.Logging(struct let label = label end) ;;

let str_list_option ?(default=Some []) ?(metavar = "STRLST") =
  let sep = "," in
  let coerce s = ExtString.String.nsplit s sep in
  fun () ->
    OptParse.Opt.value_option metavar default coerce
    (fun _ s -> Printf.sprintf "Invalid String '%s'" s)

module StringSet = BootstrapCommon.StringSet
module IntSet = BootstrapCommon.IntSet

module Options = struct
  open OptParse
  let usage = "%prog [options] --deb-native-arch=ARCH buildgraph srcgraph Packages Sources"
  let description = "output statistics in JSON format"
  let options = OptParser.make ~description ~ usage
  include BootstrapCommon.MakeOptions(struct let options = options end)

  let cycle_length = StdOpt.int_option ~default:2 ()
  let cycle_length_fas = StdOpt.int_option ~default:8 ()
  let remove_weak = StdOpt.str_option ()
  let remove_reduced = str_list_option ()
  let sapsb = StdOpt.store_true ()
  let allowsrcmismatch = StdOpt.store_true ()
  let available = StdOpt.str_option ()

  open OptParser ;;

  let prog_group = add_group options "Program specific options" in

  add options ~group:prog_group ~long_name:"max-length" ~help:"maximum length of found cycles (default=2)" cycle_length;
  add options ~group:prog_group ~long_name:"max-length-fas" ~help:"maximum length of found cycles for fas search (default=4)" cycle_length_fas;
  add options ~group:prog_group ~long_name:"remove-weak" ~help:"path to list of weak build dependencies" remove_weak;
  add options ~group:prog_group ~long_name:"sapsb" ~help:"calculate strong articulation points and strong bridges" sapsb;
  add options ~group:prog_group ~long_name:"remove-reduced" ~help:"remove droppable build dependencies supplied by comma separated list of reduced dep files" remove_reduced;
  add options ~group:prog_group ~short_name:'A' ~long_name:"available"
    ~help:"List of available packages (arch:all, crossed...) in control file format" available;

  add options ~group:prog_group ~long_name:"allowsrcmismatch" ~help:("If a binary package is "^
    "without a source package but there is a source package of same name but "^ 
    "different version, match this binary package to that source package.") allowsrcmismatch;

  include StdOptions.InputOptions;;
  let default = List.filter (fun e -> not (List.mem e ["compare"; "checkonly"; "latest";"outfile";"inputtype"])) StdOptions.InputOptions.default_options in
  StdOptions.InputOptions.add_options ~default options ;;

  include StdOptions.DistribOptions;;
  let default = List.filter (fun e -> not (List.mem e ["deb-profiles"; "deb-ignore-essential"; "deb-builds-from"])) StdOptions.DistribOptions.default_options in
  StdOptions.DistribOptions.add_debian_options ~default options ;;

end

let main () =
  let posargs = OptParse.OptParser.parse_argv Options.options in
  StdDebug.enable_debug (OptParse.Opt.get Options.verbose);
  Util.Debug.disable "Depsolver_int";
  Util.Warning.disable "Sources"; (* disable MismatchSrc warnings as exception is caught *)
  StdDebug.all_quiet (OptParse.Opt.get Options.quiet);
  let maxlengthfas = OptParse.Opt.get Options.cycle_length_fas in
  let maxlength = OptParse.Opt.get Options.cycle_length in
  let reduced_deps_files = OptParse.Opt.get Options.remove_reduced in
  let allowsrcmismatch = OptParse.Opt.get Options.allowsrcmismatch in
  let options = Options.set_deb_options () in
  let noindep = options.Debcudf.drop_bd_indep in
  let buildarch = Option.get options.Debcudf.native in
  let hostarch = match options.Debcudf.host with None -> "" | Some s -> s in
  let foreignarchs = options.Debcudf.foreign in

  let bgf, sgf, posargs = match posargs with
   | bgf::sgf::l -> bgf,sgf,l
   | _ -> fatal "you must provide buildgraph, srcgraph, Packages and Sources"
  in

  let (binlist, (fgsrclist,bgsrclist), _) = BootstrapCommon.parse_packages ~noindep Options.parse_cmdline buildarch hostarch foreignarchs posargs in

  let tables = Debcudf.init_tables (fgsrclist@bgsrclist@binlist) in
  let fgsl = List.map (Debcudf.tocudf ?inst:None ~options tables) fgsrclist in
  let bgsl = List.map (Debcudf.tocudf ?inst:None ~options tables) bgsrclist in
  let pkglist = List.map (Debcudf.tocudf ?inst:None ~options tables) binlist in
  let universe = Cudf.load_universe (BootstrapCommon.unique [pkglist;fgsl;bgsl]) in

  let module BG = BuildGraph.G in
  let module SG = SrcGraph.G in

  let ic = open_in bgf in
  let bg = BuildGraph.from_ic universe buildarch ic in
  close_in ic;

  let ic = open_in sgf in
  let sg = SrcGraph.from_ic universe buildarch ic in
  close_in ic;

  (* read package list for available packages *)
  let availableset =
    if OptParse.Opt.is_set Options.available then
      BootstrapCommon.read_package_file ~archs:(buildarch::hostarch::foreignarchs) (Debcudf.tocudf ?inst:None ~options tables) (OptParse.Opt.get    Options.available)
    else CudfAdd.Cudf_set.empty
  in

  let module BGE = BuildGraphExtras.Make(struct let univ = universe end) in
  let module BGS = BuildGraphStats.Make(struct let univ = universe end) in
  let module SGE = SrcGraphExtras.Make(struct let univ = universe end) in
  let module SGS = SrcGraphStats.Make(struct let univ = universe end) in

  let binset = BootstrapCommon.get_bin_packages (BootstrapCommon.srcbin_table ~available:availableset ~allowmismatch:allowsrcmismatch universe) in

  let type1, type2, type3 = SGS.self_cycles binset sg in

  let srcpkglist = BGE.srcpkglist_of_g bg in
  let weak_file =
    if OptParse.Opt.is_set Options.remove_weak then
      OptParse.Opt.get Options.remove_weak
    else
      ""
  in
  let reduced_deps_ht, weak_deps_set = BootstrapCommon.get_reduced_deps_ht ~weak_file (OptParse.Opt.is_set Options.remove_weak) (buildarch::foreignarchs) srcpkglist reduced_deps_files in
  BGE.remove_build_deps reduced_deps_ht bg;

  let scc = List.filter_map (function [] | [_] -> None | s -> Some (BuildGraph.Oper.subgraph bg s)) (BuildGraph.Comp.scc_list bg) in

  (* cudf to debian binary/source converter shorthands *)
  let c2b = BootstrapCommon.debbintriplet_of_cudfpkg in
  let c2s = BootstrapCommon.debsrctuple_of_cudfpkg in
  let c2bl = List.map c2b in
  let c2sl = List.map c2s in

  let result = {
    srcgraph = {
      snr_vertex = SG.nb_vertex sg;
      snr_edges = SG.nb_edges sg;
      type1cycles = List.map (fun (pkg, d1, d2) -> (c2s pkg, c2bl d1, c2bl d2)) type1;
      type2cycles = List.map (fun (pkg, d1, d2) -> (c2s pkg, c2bl d1, c2bl d2)) type2;
      type3cycles = List.map (fun (pkg, deps) -> (c2s pkg, c2bl deps)) type3;
    };
    buildgraph = {
      bnr_vertex = BG.nb_vertex bg;
      bnr_edges = BG.nb_edges bg;
      sccs = List.map (fun sg ->
        let cycles, cycleedge = if maxlength > 0 then begin
          let cycles = BuildGraph.Cycles.johnson ~maxlength sg in
          cycles, (BGS.edges_in_most_cycles sg cycles)
        end else [], [] in
        let fas = if maxlengthfas > 0 then begin
          let ht_fas = Hashtbl.create (BG.nb_edges sg) in
          BuildGraph.EdgeSet.iter (fun (src,_,pkg) ->
            Hashtbl.replace ht_fas src (pkg::(Hashtbl.find_default ht_fas src []))
          ) (BGE.calculate_fas ~maxlength:maxlengthfas sg);
          Hashtbl.fold (fun k v acc -> (k,v)::acc) ht_fas []
        end else [] in
        let sap, sb = if OptParse.Opt.get Options.sapsb then begin
          let sap = BuildGraph.Utils.find_strong_articulation_points sg in
          let sb = BuildGraph.Utils.find_strong_bridges sg in
          sap, sb
        end else [], [] in
        {
          sg_vertex = BG.nb_vertex sg;
          sg_edges = BG.nb_edges sg;
          cycles = List.map BGE.variantlist_of_vlist cycles;
          cycleedge = List.map (fun ((v1,_,v2),c) -> ((BGE.variant_of_vertex v1), (BGE.variant_of_vertex v2)), c) cycleedge;
          builddeps = List.map (fun (p,deps) -> c2s p, c2bl deps) (BGS.min_builddep sg);
          ratio_source = List.map (fun (s,b,n,o) -> c2s s, b, c2bl n, c2sl o) (BGS.ratio_source sg);
          ratio_binary = List.map (fun (b,s,o) -> c2b b, s, c2sl o) (BGS.ratio_binary sg);
          weak = List.map (fun (pkg, deps) -> c2s pkg, c2bl deps) (BGS.only_weak_missing weak_deps_set sg);
          srcbinstats = List.map (fun (v,s,p) -> (BGE.variant_of_vertex v), s, p) (BGS.get_src_bin_stats sg);
          fas = List.map (fun (p,deps) -> c2s (BGE.pkg_of_vertex p), c2bl (BGE.pkglist_of_vlist deps)) fas;
          sap = List.map (fun (p,i) -> (BGE.variant_of_vertex p), i) sap;
          sb = List.map (fun ((v1,_,v2),i) -> (BGE.variant_of_vertex v1, BGE.variant_of_vertex v2), i) sb;
        }
      ) scc;
    };
  } in

  (* we let this program output un-prettified JSON because to prettify we'd
   * have to store the JSON data in a string which easily exceeds the maximum
   * OCaml string length on 32 bit systems. Instead, the output of this program
   * can be piped to ydump to prettify it.
   *
   * https://github.com/mjambon/atdgen/issues/43
   * *)
  let buf = Buffer.create 1000 in
  Datatypes_j.write_stats buf result;
  Buffer.output_buffer stdout buf;
;;

main ();;