[Pkg-ocaml-maint-commits] r6257 - in /trunk/tools/ocaml_transition_monitor: ./ Makefile ocaml-status.css ocaml_transition_monitor.mll
glondu-guest at users.alioth.debian.org
glondu-guest at users.alioth.debian.org
Wed Feb 25 00:05:41 UTC 2009
Author: glondu-guest
Date: Wed Feb 25 00:05:41 2009
New Revision: 6257
URL: http://svn.debian.org/wsvn/?sc=1&rev=6257
Log:
Add a script to monitor transitions
Added:
trunk/tools/ocaml_transition_monitor/
trunk/tools/ocaml_transition_monitor/Makefile
trunk/tools/ocaml_transition_monitor/ocaml-status.css
trunk/tools/ocaml_transition_monitor/ocaml_transition_monitor.mll
Added: trunk/tools/ocaml_transition_monitor/Makefile
URL: http://svn.debian.org/wsvn/trunk/tools/ocaml_transition_monitor/Makefile?rev=6257&op=file
==============================================================================
--- trunk/tools/ocaml_transition_monitor/Makefile (added)
+++ trunk/tools/ocaml_transition_monitor/Makefile Wed Feb 25 00:05:41 2009
@@ -1,0 +1,10 @@
+all: ocaml_transition_monitor.byte
+
+%.byte: %.ml
+ ocamlfind ocamlc -package ocsigen.xhtml,str -linkpkg -o $@ $<
+
+%.ml: %.mll
+ ocamllex $<
+
+clean:
+ rm -f Packages.* *.html *.cm* *.byte *~
Added: trunk/tools/ocaml_transition_monitor/ocaml-status.css
URL: http://svn.debian.org/wsvn/trunk/tools/ocaml_transition_monitor/ocaml-status.css?rev=6257&op=file
==============================================================================
--- trunk/tools/ocaml_transition_monitor/ocaml-status.css (added)
+++ trunk/tools/ocaml_transition_monitor/ocaml-status.css Wed Feb 25 00:05:41 2009
@@ -1,0 +1,41 @@
+body {
+ font-family: sans-serif;
+}
+h1 {
+ margin: 0;
+ padding: 5px 0px 5px 150px;
+ height: 50px;
+ background: #df0451;
+ color: white;
+ margin-bottom: 1em;
+ border-bottom: 2px solid #af0031;
+ background-image: url(http://caml.inria.fr//pub/logos/caml-inria-fr.128x58.gif);
+ background-repeat: no-repeat;
+}
+div.status {
+ text-align: center;
+}
+div.status table a {
+ text-decoration: none;
+}
+div#footer {
+ margin-top: 2em;
+ font-size: 60%;
+}
+
+.good {
+ background: LightGreen;
+}
+
+.bad {
+ background: Salmon;
+}
+
+.unknown {
+ background: Cornsilk;
+}
+
+td {
+ border-style: solid;
+ border-width: 1px;
+}
Added: trunk/tools/ocaml_transition_monitor/ocaml_transition_monitor.mll
URL: http://svn.debian.org/wsvn/trunk/tools/ocaml_transition_monitor/ocaml_transition_monitor.mll?rev=6257&op=file
==============================================================================
--- trunk/tools/ocaml_transition_monitor/ocaml_transition_monitor.mll (added)
+++ trunk/tools/ocaml_transition_monitor/ocaml_transition_monitor.mll Wed Feb 25 00:05:41 2009
@@ -1,0 +1,242 @@
+(*
+ Copyright © 2009 Stéphane Glondu <steph at glondu.net>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Dependencies: wget, bzip2, ocsigen-dev.
+*)
+
+{
+ let ocaml_version = "3.11.0"
+
+ let mirror = "http://ftp.fr.debian.org/debian"
+ let suite = "unstable"
+ let section = "main"
+
+ let architectures =
+ [ "alpha"; "amd64"; "armel"; "hppa"; "i386"; "ia64"; "mips"; "mipsel"; "powerpc"; "s390"; "sparc" ]
+
+ module S = Set.Make(String)
+ module M = Map.Make(String)
+
+ open Printf
+ open XHTML.M
+
+ type source_package = {
+ sname: string;
+ sdeps: string list;
+ sbins : string list;
+ sversion: string;
+ }
+ type binary_package = {
+ bname: string;
+ bdeps: string list;
+ bsrc: string;
+ bversion: string;
+ bnmu: int;
+ }
+
+ let headers_to_keep =
+ [ "Package"; "Binary"; "Version"; "Build-Depends"; "Depends"; "Architecture"; "Source"; "Provides" ]
+
+ type status = Unknown | Up_to_date | Outdated
+ let string_of_status = function
+ | Unknown -> "unknown"
+ | Up_to_date -> "good"
+ | Outdated -> "bad"
+
+ let skip_download = ref false
+ let quiet_mode = ref false
+
+ let progress x =
+ if !quiet_mode then ifprintf stderr x else fprintf stderr x
+}
+
+let name = ['A'-'Z' 'a'-'z' '0'-'9' '-' '.' ':' '~' '+']+
+
+rule entry accu = parse
+ | ([^':' '\n']+ as header) ":"
+ {
+ if List.mem header headers_to_keep then
+ (entry ((header, values [] lexbuf)::accu) lexbuf)
+ else
+ (skip lexbuf; entry accu lexbuf)
+ }
+ | eof | '\n' { if accu = [] then raise End_of_file else accu }
+and values accu = parse
+ | name as name { values (name::accu) lexbuf }
+ | [' ' ',' '|']+ { values accu lexbuf }
+ | '(' [^')']* ')' | "\n " | '[' [^']']* ']'
+ { values accu lexbuf }
+ | "\n " { values accu lexbuf }
+ | "\n" { accu }
+and skip = parse
+ | ([^'\n']* "\n ")* [^'\n']* "\n" { () }
+
+{
+ let get_one = function
+ | [a] -> a
+ | x -> invalid_arg (sprintf "[%s] should have exactly one element" (String.concat ", " x))
+
+ let assoc ?default x xs =
+ try List.assoc x xs
+ with Not_found -> match default with
+ | None -> invalid_arg ("Not_found: "^x)
+ | Some y -> y
+
+ let parse_source channel =
+ let lexbuf = Lexing.from_channel channel in
+ let result = ref M.empty in
+ let rec aux () =
+ let entry = entry [] lexbuf in
+ let name = get_one (assoc "Package" entry) in
+ let entry = {
+ sname = name;
+ sdeps = assoc ~default:[] "Build-Depends" entry;
+ sbins = assoc "Binary" entry;
+ sversion = get_one (assoc "Version" entry);
+ } in
+ result := M.add name entry !result;
+ aux ()
+ in try aux () with End_of_file -> !result
+
+ let parse_binary channel =
+ let lexbuf = Lexing.from_channel channel in
+ let result = ref M.empty in
+ let rec aux () =
+ let entry = entry [] lexbuf in
+ let name = get_one (assoc "Package" entry) in
+ let entry = {
+ bname = name;
+ bdeps = (assoc ~default:[] "Depends" entry) @ (assoc ~default:[] "Provides" entry);
+ bsrc = get_one (assoc ~default:[name] "Source" entry);
+ bversion = get_one (assoc "Version" entry);
+ bnmu = 0;
+ } in
+ result := M.add name entry !result;
+ aux ()
+ in try aux () with End_of_file -> !result
+
+ let runtime_ocaml_regexp = Str.regexp "^ocaml\\(-base\\)?\\(-nox\\)?-\\([0-9.]+\\)$"
+ let build_ocaml_regexp = Str.regexp "^ocaml\\(-nox\\)?$"
+
+ let depends_on_ocaml x =
+ let rec aux = function
+ | [] -> None
+ | x::xs ->
+ if Str.string_match runtime_ocaml_regexp x 0 then
+ Some (Str.matched_group 3 x)
+ else aux xs
+ in aux x.bdeps
+
+ let build_depends_on_ocaml x =
+ let rec aux = function
+ | [] -> false
+ | x::xs ->
+ if Str.string_match build_ocaml_regexp x 0 then
+ true
+ else aux xs
+ in aux x.sdeps
+
+ let with_in_file file f =
+ let chan = open_in_bin file in
+ try
+ let res = f chan in
+ close_in chan; res
+ with e -> close_in chan; raise e
+
+ let with_out_file file f =
+ let chan = open_out_bin file in
+ try
+ let res = f chan in
+ close_out chan; res
+ with e -> close_out chan; raise e
+
+ let get_arch_status arch =
+ let binaries = with_in_file ("Packages."^arch) parse_binary in
+ let runtime_versions = M.fold
+ (fun k pkg accu -> match depends_on_ocaml pkg with
+ | None -> accu
+ | Some version -> M.add k (pkg, version) accu)
+ binaries M.empty in
+ let compiled_sources = M.fold
+ (fun k (pkg, version) accu ->
+ M.add pkg.bsrc (version = ocaml_version) accu)
+ runtime_versions M.empty in
+ compiled_sources
+
+ let get_sources () =
+ let sources = with_in_file "Packages.source" parse_source in
+ let sources = M.fold
+ (fun k pkg accu ->
+ if build_depends_on_ocaml pkg
+ || pkg.sname = "ocaml"
+ || pkg.sname = "dh-ocaml" then M.add k pkg accu else accu)
+ sources M.empty in
+ sources
+
+ let get_package_lists () =
+ List.for_all
+ (fun arch ->
+ let url = sprintf "%s/dists/%s/%s/binary-%s/Packages.bz2" mirror suite section arch in
+ let cmd = sprintf "wget -q -O- '%s' | bzcat > Packages.%s" url arch in
+ progress "Downloading Packages.%s...%!" arch;
+ let r = Sys.command cmd in
+ progress "\n%!";
+ r = 0)
+ architectures
+ && (let url = sprintf "%s/dists/%s/%s/source/Sources.bz2" mirror suite section in
+ let cmd = sprintf "wget -q -O- '%s' | bzcat > Packages.source" url in
+ progress "Downloading Packages.source...%!";
+ let r = Sys.command cmd in
+ progress "\n%!";
+ r = 0)
+
+ let main () =
+ let all_binaries = List.map get_arch_status architectures in
+ let all_sources = List.sort compare
+ (M.fold (fun k _ accu -> k::accu) (get_sources ()) [])
+ in
+ let status pkg = List.map
+ (fun x ->
+ try if M.find pkg x then Up_to_date else Outdated
+ with Not_found -> Unknown) all_binaries
+ in
+ let status = List.map (fun pkg -> (pkg, status pkg)) all_sources in
+ let all_sources = List.map
+ (fun (pkg, status) -> tr
+ (td [a ~a:[a_href (uri_of_string ("http://packages.qa.debian.org/"^pkg))] [pcdata pkg];
+ br ();
+ small [pcdata "[";
+ a ~a:[a_href (uri_of_string ("http://buildd.debian.org/~luk/status/package.php?p="^pkg))] [pcdata "buildd"];
+ pcdata "]";
+ ]])
+ (List.map (fun x -> let x = string_of_status x in td ~a:[a_class [x]] [pcdata x]) status))
+ status
+ in
+ let summary = tablex
+ ~thead:(thead (tr (th [pcdata "Source package"]) (List.map (fun arch -> th [pcdata arch]) architectures)) [])
+ (match all_sources with x::xs -> tbody x xs | _ -> invalid_arg "there must be at least one package")
+ []
+ in
+ let page_title = "Monitoring OCaml transition to "^ocaml_version in
+ let html = html
+ (head (title (pcdata page_title)) [link ~a:[a_rel [`Stylesheet]; a_href (uri_of_string "ocaml-status.css")] ()])
+ (body [h1 [pcdata page_title];
+ div ~a:[a_class ["status"]] [summary]])
+ in
+ with_out_file "ocaml_transition_monitor.html"
+ (fun chan -> output (fun s -> fprintf chan "%s%!" s) html)
+
+ let _ =
+ let speclist = [
+ "--skip-download", Arg.Set skip_download, "Skip downloading package list files";
+ "--quiet", Arg.Set quiet_mode, "Quiet mode";
+ ] in
+ Arg.parse speclist (fun s -> raise (Arg.Bad s)) "Generates ocaml_transition_monitor.html";
+ if not !skip_download && not (get_package_lists ()) then failwith "Error while downloading lists!";
+ main ()
+}
More information about the Pkg-ocaml-maint-commits
mailing list