Release coccinelle-0.2.2-rc1
[bpt/coccinelle.git] / tools / split_patch.ml
1 (*
2 * Copyright 2005-2010, Ecole des Mines de Nantes, University of Copenhagen
3 * Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller, Nicolas Palix
4 * This file is part of Coccinelle.
5 *
6 * Coccinelle is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, according to version 2 of the License.
9 *
10 * Coccinelle is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
17 *
18 * The authors reserve the right to distribute this or future versions of
19 * Coccinelle under other licenses.
20 *)
21
22
23 (* split patch per file *)
24
25 let is_diff = Str.regexp "diff "
26 let split_patch i =
27 let patches = ref [] in
28 let cur = ref [] in
29 let rec loop _ =
30 let l = input_line i in
31 (if Str.string_match is_diff l 0
32 then
33 (if List.length !cur > 0
34 then begin patches := List.rev !cur :: !patches; cur := [l] end)
35 else cur := l :: !cur);
36 loop() in
37 try loop() with End_of_file -> !patches
38
39 (* ------------------------------------------------------------------------ *)
40
41 (* can get_maintainers takea file as an argument, or only a patch? *)
42 let resolve_maintainers cmd patches =
43 let maintainer_table = Hashtbl.create (List.length patches) in
44 List.iter
45 (function
46 diff_line::rest ->
47 (match Str.split (Str.regexp " a/") diff_line with
48 [before;after] ->
49 (match Str.split (Str.regexp " ") after with
50 file::_ ->
51 (match Common.cmd_to_list (cmd ^ " " ^ file) with
52 [info] ->
53 let cell =
54 try Hashtbl.find maintainer_table info
55 with Not_found ->
56 let cell = ref [] in
57 Hashtbl.add maintainer_table info cell;
58 cell in
59 cell := (diff_line :: rest) :: !cell
60 | _ -> failwith "badly formatted maintainer result")
61 | _ -> failwith "filename not found")
62 | _ ->
63 failwith (Printf.sprintf "prefix a/ not found in %s" diff_line))
64 | _ -> failwith "bad diff line")
65 patches;
66 maintainer_table
67
68 (* ------------------------------------------------------------------------ *)
69
70 let print_all o l =
71 List.iter (function x -> Printf.fprintf o "%s\n" x) l
72
73 let make_output_files template maintainer_table patch =
74 let ctr = ref 0 in
75 Hashtbl.iter
76 (function maintainers ->
77 function diffs ->
78 ctr := !ctr + 1;
79 let o = open_out (Printf.sprintf "%s%d" patch !ctr) in
80 Printf.fprintf o "To: %s\n\n" maintainers;
81 print_all o template;
82 List.iter (print_all o) (List.rev !diffs);
83 close_out o)
84 maintainer_table
85
86 (* ------------------------------------------------------------------------ *)
87
88 let command = ref "get_maintainers.pl"
89 let file = ref ""
90
91 let options =
92 ["-cmd", Arg.String (function x -> command := x), "get maintainer command"]
93
94 let usage = ""
95
96 let anonymous x = file := x
97
98 let _ =
99 Arg.parse (Arg.align options) (fun x -> file := x) usage;
100 let i = open_in !file in
101 let patches = split_patch i in
102 let maintainer_table = resolve_maintainers !command patches in
103 let template = Common.cmd_to_list (Printf.sprintf "cat %s.tmp" !file) in
104 make_output_files template maintainer_table !file