[kernel] r7594 - dists/trunk/scripts
Sven Luther
luther at costa.debian.org
Tue Oct 10 21:05:33 UTC 2006
Author: luther
Date: Tue Oct 10 21:05:32 2006
New Revision: 7594
Modified:
dists/trunk/scripts/kconfig.ml
Log:
Added support for diffing config files in kconfig.ml.
Modified: dists/trunk/scripts/kconfig.ml
==============================================================================
--- dists/trunk/scripts/kconfig.ml (original)
+++ dists/trunk/scripts/kconfig.ml Tue Oct 10 21:05:32 2006
@@ -1,41 +1,120 @@
#!/usr/bin/ocamlrun /usr/bin/ocaml
+(*
+ * kconfig.ml Copyright (C) 2006 Sven Luther <sl at powerlinux.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *)
+
+(*
+ * Syntax :
+ * kconfig.ml <action> [-bs sourcedir] <file> [<file>]
+ * <action> : single | check | create | diff
+ * <file> : -c <filename> | [-b basedir | -ba basedir] -a arch [-s subarch] -f flavour
+ *)
+
+let usage_string =
+ "Usage:\n\n" ^
+ " Check single config file : ./kconfig.ml single -c <filename>\n" ^
+ " Create config file : ./kconfig.ml create [ -ba <dir> | -b <dir> ] -a <arch> [ -s <subarch> ] -f <flavour>\n" ^
+ " Check all config files : ./kconfig.ml check [ -ba <dir> | -b <dir> ] [ -bs <dir> ]\n" ^
+ " Diff two config files : ./kconfig.ml diff [ -ba <dir> | -b <dir> ] config config\n" ^
+ " where config is : (-c <filename> | -a <arch> [ -s <subarch> ] -f <flavour>)\n" ^
+ "\nOptions:\n"
+
+(* Command line argument parsing *)
+exception Bad_action of string
+exception Double_action of string
+exception Bad_args of string
+
+type action = Single | Check | Create | Diff | NoAction | Help
+let action = ref NoAction
+let set_action a =
+ if !action != NoAction then raise (Double_action a) else
+ match a with
+ | "check" -> action := Check
+ | "create" -> action := Create
+ | "diff" -> action := Diff
+ | "single" -> action := Single
+ | _ -> raise (Bad_action a)
+let string_of_action = function
+ | Single -> "single"
+ | Check -> "check"
+ | Create -> "create"
+ | Diff -> "diff"
+ | NoAction -> "NoAction"
+ | Help -> "Help"
-(* Command line arguments parsing *)
let basedir = ref "debian/arch"
let sourcedir = ref "."
-let arch = ref ""
-let subarch = ref ""
-let flavour = ref ""
-let config_name = ref ""
-let verbose = ref false
-let archindir = ref false
+let set_basedir archindir dir =
+ basedir := if archindir then Filename.dirname dir else dir
-type action = Single | Create | Check
-let action = ref Create
+type kind = TConfig | TArch | TSubarch | TFlavour
+type temp = (kind * string) list
+let temp : temp ref = ref []
+let set_temp k s = temp := (k,s) :: !temp
+let rec print_temp = function
+ | [] -> ()
+ | (TConfig,s)::t -> Printf.printf "<Config %s>\n" s; print_temp t
+ | (TArch,s)::t -> Printf.printf "<Arch %s>\n" s; print_temp t
+ | (TSubarch,s)::t -> Printf.printf "<Subarch %s>\n" s; print_temp t
+ | (TFlavour,s)::t -> Printf.printf "<Flavour %s>\n" s; print_temp t
+let string_of_temp_error a s l =
+ let rec pte e = function
+ | [] -> e
+ | (TConfig,s)::t -> pte (e ^ (Printf.sprintf "-c %s " s)) t
+ | (TArch,s)::t -> pte (e ^ (Printf.sprintf "-a %s " s)) t
+ | (TSubarch,s)::t -> pte (e ^ (Printf.sprintf "-s %s " s)) t
+ | (TFlavour,s)::t -> pte (e ^ (Printf.sprintf "-f %s " s)) t
+ in
+ (match a with Some a -> Printf.sprintf"-a %s " a | None -> "") ^
+ (match s with Some s -> Printf.sprintf "-s %s " s | None -> "") ^
+ (pte "" l)
+
+type config = Config of string | Flavour of string * string | Subarch of string * string * string
+let config_of_temp t =
+ let rec config_of_temp ta ts l = match ta, ts, l with
+ | None, None, (TArch,a)::t -> config_of_temp (Some a) None t
+ | Some a, None, (TSubarch,s)::t -> config_of_temp (Some a) (Some s) t
+ | Some a, Some s, (TFlavour,f)::t -> (Subarch (a,s,f))::(config_of_temp None None t)
+ | Some a, None, (TFlavour,f)::t -> (Flavour (a,f))::(config_of_temp None None t)
+ | None, None, (TConfig,f)::t -> (Config f)::(config_of_temp None None t)
+ | None, None, [] -> []
+ | _, _, _ -> raise (Bad_args (string_of_temp_error ta ts l))
+ in config_of_temp None None t
+
+let rec print_configs = function
+ | [] -> ()
+ | (Config f) :: t -> Printf.printf "Config file: %s\n" f; print_configs t
+ | (Flavour (a,f)) :: t -> Printf.printf "Arch: %s, Flavour: %s\n" a f; print_configs t
+ | (Subarch (a,s,f)) :: t -> Printf.printf "Arch: %s, Subarch: %s, Flavour: %s\n" a s f; print_configs t
-let set_action a () = action := a
+let verbose = ref false
let spec = [
- "-b", Arg.Set_string basedir, "base dir of the arch configurations [default: debian/arch]";
+ "-b", Arg.String (set_basedir false), "specify basedir of the arch configurations [default: debian/arch]";
+ "-ba", Arg.String (set_basedir true), "specify basedir of the arch configurations (after stripping arch dir) [default: debian/arch]";
"-bs", Arg.Set_string sourcedir, "base source dir containing the patched debian linux source tree [default: .]";
- "-ba", Arg.Set archindir, "basedir includes arch";
- "-a", Arg.Set_string arch, "arch";
- "-s", Arg.Set_string subarch, "subarch";
- "-f", Arg.Set_string flavour, "flavour";
- "-v", Arg.Set verbose, "verbose";
- "-c", Arg.Unit (set_action Check), "check";
+ "-a", Arg.String (set_temp TArch), "specify config arch";
+ "-s", Arg.String (set_temp TSubarch), "specify config subarch";
+ "-f", Arg.String (set_temp TFlavour), "specify config flavour";
+ "-c", Arg.String (set_temp TConfig), "specify config file name";
+ "-v", Arg.Set verbose, "verbose output";
+ "-h", Arg.Unit (function () -> action := Help), "Display this list of options";
]
-let usage =
- "Check single config file : ./kconfig.ml config_file\n" ^
- "Create config file : ./kconfig.ml [ -ba ] [ -b basedir ] -a arch [ -s subarch ] -f flavour" ^ "\n" ^
- "Check all config files : ./kconfig.ml -c [ -ba ] [ -b basedir ] [ -bs sourcedir ] [ -a arch ] [ -s subarch ] [ -f flavour ]" ^ "\n"
-
-let () = Arg.parse
- spec
- (function s -> config_name := s; action := Single)
- usage
-let usage () = Arg.usage spec usage
+let usage () = Arg.usage spec usage_string
(* Config file parsing *)
type options =
@@ -113,6 +192,27 @@
with Sys_error s ->
if force then raise (Sys_error s) else m
+(* Diffing two config files *)
+module Diff = Map.Make (String)
+type diff = Add of options | Del of options | Change of options * options
+let diff_configs a b =
+ let diff1 n v (b,d) = try
+ let v' = C.find n b in
+ let b = C.remove n b in
+ if v = v' then b, d else b, Diff.add n (Change (v,v')) d
+ with Not_found -> b, Diff.add n (Add v) d
+ in
+ let diff2 n v d = Diff.add n (Del v) d in
+ let b,d = C.fold diff1 a (b, Diff.empty) in
+ C.fold diff2 b d
+let print_diff d =
+ let print_diff n = function
+ | Add v -> Printf.printf "+ "; print_option v
+ | Del v -> Printf.printf "- "; print_option v
+ | Change (v,v') -> Printf.printf "+ "; print_option v; Printf.printf "- "; print_option v'
+ in
+ Diff.iter print_diff d
+
(* Defines parsing *)
type define =
| Defines_Base of string
@@ -175,46 +275,97 @@
let print_defines m = List.iter print_define m
(* Main functionality *)
-let get_archdir () = if !archindir then Filename.dirname !basedir else !basedir
-
-let do_single () =
- try
- begin if !verbose then Printf.eprintf "Reading config file %s" !config_name end;
- let config = open_in !config_name in
+let create_config = function
+ | Config c ->
+ begin if !verbose then Printf.eprintf "Reading config file %s" c end;
+ let config = open_in c in
let m = parse_config config C.empty in
- print_config m;
- close_in config
- with Sys_error s -> Printf.eprintf "Error: %s\n" s
-
-let do_create () =
- if !arch <> "" && !flavour <> "" then begin
- if !verbose then
- Printf.eprintf "Creating config file for arch %s, subarch %s, flavour %s (basedir is %s)\n" !arch !subarch !flavour !basedir;
- let dir = get_archdir () in
- let m = parse_config_file (dir ^ "/config") C.empty false in
- let archdir = dir ^ "/" ^ !arch in
- let m = parse_config_file (archdir ^ "/config") m false in
- let m, archdir =
- if !subarch <> "" && !subarch <> "none" then
- let archdir = archdir ^ "/" ^ !subarch in
- parse_config_file (archdir ^ "/config") m false, archdir
- else m, archdir
- in
- let m = parse_config_file (archdir ^ "/config." ^ !flavour) m true in
- print_config m
- end
- else
- usage ()
-
-let do_check () =
- let dir = get_archdir () in
- begin if !verbose then Printf.eprintf "Checking config files in %s\n" dir end;
- let m = parse_defines_file (dir ^ "/defines") [] true in
- print_defines m
+ let () = close_in config in
+ m
+ | Subarch (a,s,f) ->
+ if !verbose then
+ Printf.eprintf "Creating config file for arch %s, subarch %s, flavour %s (basedir is %s)\n" a s f !basedir;
+ let m = parse_config_file (!basedir ^ "/config") C.empty false in
+ let archdir = !basedir ^ "/" ^ a in
+ let m = parse_config_file (archdir ^ "/config") m false in
+ let archdir = archdir ^ "/" ^ s in
+ let m = parse_config_file (archdir ^ "/config") m false in
+ parse_config_file (archdir ^ "/config." ^ f) m true
+ | Flavour (a,f) ->
+ if !verbose then
+ Printf.eprintf "Creating config file for arch %s, flavour %s (basedir is %s)\n" a f !basedir;
+ let m = parse_config_file (!basedir ^ "/config") C.empty false in
+ let archdir = !basedir ^ "/" ^ a in
+ let m = parse_config_file (archdir ^ "/config") m false in
+ parse_config_file (archdir ^ "/config." ^ f) m true
+
+let do_single configs =
+ match configs with
+ | [] -> raise (Sys_error "Too few arguments for action single")
+ | (Config c)::[] ->
+ let m = create_config (Config c) in
+ print_config m
+ | _::[] -> raise (Sys_error "Only config file supported for action single")
+ | _ -> raise (Sys_error "Too many arguments for action single")
+
+let do_create configs =
+ match configs with
+ | [] -> raise (Sys_error "Too few arguments for action create")
+ | (Config c)::[] -> raise (Sys_error "config file not supported for action create")
+ | (Subarch (a,s,f))::[] ->
+ let m = create_config (Subarch (a,s,f)) in
+ print_config m
+ | (Flavour (a,f))::[] ->
+ let m = create_config (Flavour (a,f)) in
+ print_config m
+ | _ -> raise (Sys_error "Too many arguments for action create")
+
+let do_check configs =
+ match configs with
+ | [] ->
+ begin if !verbose then Printf.eprintf "Checking config files in %s\n" !basedir end;
+ let m = parse_defines_file (!basedir ^ "/defines") [] true in
+ print_defines m
+ | _ -> raise (Sys_error "Too many arguments for action check")
+
+let do_diff configs =
+ match configs with
+ | [] | _::[] -> raise (Sys_error "Too few arguments for action diff")
+ | a::b::[] ->
+ let ma = create_config a in
+ let mb = create_config b in
+ let d = diff_configs ma mb in
+ print_diff d
+ | _ -> raise (Sys_error "Too many arguments for action check")
+
+let print_error s = Printf.eprintf "Error:\n\n %s\n\n" s; usage ()
let () = try
+ let () = Arg.parse spec set_action usage_string in
+ let configs : config list = config_of_temp (List.rev !temp) in
match !action with
- | Single -> do_single ()
- | Create -> do_create ()
- | Check -> do_check ()
- with Sys_error s -> Printf.eprintf "Error: %s\n" s; usage ()
+ | Single -> do_single configs
+ | Create -> do_create configs
+ | Check -> do_check configs
+ | Diff -> do_diff configs
+ | NoAction -> print_error "no action provided"
+ | Help -> usage ()
+ with
+ | Sys_error s -> print_error s
+ | Bad_args s -> print_error (Printf.sprintf "while parsing args at \"%s\"" s)
+ | Bad_action s -> print_error (Printf.sprintf "unrecognized action \"%s\"" s)
+ | Double_action s ->print_error (Printf.sprintf "only one action allowed \"%s\"" s)
+
+(*
+ * TODO items
+ *
+ * full parsing of defines.
+ * parsing of kernel kbuild tree.
+ * parsing of kernel/module Makefiles.
+ * generation of module description files.
+ *
+ * organisation of kernels in a per-version, per-arch/subarch/flavour way in the archive.
+ * (outside of the normal udeb/deb stable/testing/unstable/experimental archive).
+ * Linking into the normal distributions, out of this alternate archive.
+ * Implications for the archive tools : new upload queues.
+ *)
More information about the Kernel-svn-changes
mailing list