Coccinelle release-1.0.0-rc11
[bpt/coccinelle.git] / tools / gitsort.ml
1 (*
2 * Copyright 2012, INRIA
3 * Julia Lawall, Gilles Muller
4 * Copyright 2010-2011, INRIA, University of Copenhagen
5 * Julia Lawall, Rene Rydhof Hansen, Gilles Muller, Nicolas Palix
6 * Copyright 2005-2009, Ecole des Mines de Nantes, University of Copenhagen
7 * Yoann Padioleau, Julia Lawall, Rene Rydhof Hansen, Henrik Stuart, Gilles Muller, Nicolas Palix
8 * This file is part of Coccinelle.
9 *
10 * Coccinelle is free software: you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation, according to version 2 of the License.
13 *
14 * Coccinelle is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with Coccinelle. If not, see <http://www.gnu.org/licenses/>.
21 *
22 * The authors reserve the right to distribute this or future versions of
23 * Coccinelle under other licenses.
24 *)
25
26
27 (* sort a list of git codes such that the most recent comes first *)
28
29 let git_home = ref "/home/julia/linux-2.6"
30
31 let unwind_protect f cleanup =
32 try f ()
33 with e -> begin cleanup e; raise e end
34
35 let (with_open_infile: string -> ((in_channel) -> 'a) -> 'a) = fun file f ->
36 let chan = open_in file in
37 unwind_protect (fun () ->
38 let res = f chan in
39 close_in chan;
40 res)
41 (fun e -> close_in chan)
42
43 (* ----------------------------------------------------------------------- *)
44
45 let months =
46 [("Jan",1);("Feb",2);("Mar",3);("Apr",4);("May",5);("Jun",6);("Jul",7);
47 ("Aug",8);("Sep",9);("Oct",10);("Nov",11);("Dec",12)]
48
49 let antimonths =
50 [(1,31);(2,28);(3,31);(4,30);(5,31); (6,30);(7,31);(8,31);(9,30);(10,31);
51 (11,30);(12,31);(0,31)]
52
53 let normalize (year,month,day,hour,minute,second) =
54 if hour < 0
55 then
56 let (day,hour) = (day - 1,hour + 24) in
57 if day = 0
58 then
59 let month = month - 1 in
60 let day = List.assoc month antimonths in
61 let day =
62 if month = 2 && year / 4 * 4 = year && not (year / 100 * 100 = year)
63 then 29
64 else day in
65 if month = 0
66 then (year-1,12,day,hour,minute,second)
67 else (year,month,day,hour,minute,second)
68 else (year,month,day,hour,minute,second)
69 else (year,month,day,hour,minute,second)
70
71 exception Fail of string
72
73 let read_info code =
74 let _ =
75 Sys.command
76 (Printf.sprintf
77 "pushd %s >& /dev/null ; git log %s^..%s | grep Date: > /tmp/gitsort_info ; popd >& /dev/null"
78 !git_home code code) in
79 with_open_infile "/tmp/gitsort_info" (fun i ->
80 let l =
81 try input_line i
82 with End_of_file -> raise (Fail "bad git file") in
83 match Str.split (Str.regexp " ") l with
84 [date;_;_;weekday;month;day;time;year;offset] ->
85 let day = int_of_string day in
86 let month = List.assoc month months in
87 let year = int_of_string year in
88 (match Str.split (Str.regexp ":") time with
89 [hour;minute;second] ->
90 let hour = int_of_string hour in
91 let minute = int_of_string minute in
92 let second = int_of_string second in
93 let modifier =
94 match String.get offset 0 with
95 '-' -> -1
96 | '+' -> 1
97 | _ -> raise (Fail "bad offset") in
98 (if not (String.sub offset 3 2 = "00")
99 then raise (Fail "require 0 minutes difference"));
100 let hour =
101 hour + (modifier * (int_of_string (String.sub offset 1 2))) in
102 normalize (year,month,day,hour,minute,second)
103 | _ -> raise (Fail "bad date2"))
104 | l -> raise (Fail ("bad date1: "^(String.concat "|" l))))
105
106 let rec get_dates = function
107 [] -> []
108 | code::rest ->
109 let date =
110 try Some (read_info code)
111 with
112 Fail s -> Printf.printf "problem in %s: %s\n" code s; None
113 | _ -> Printf.printf "problem in %s\n" code; None in
114 match date with
115 Some date -> (date,code)::(get_dates rest)
116 | None -> get_dates rest
117
118 let get_codes file =
119 let gits = ref ([] : string list) in
120 with_open_infile file (fun i ->
121 let rec loop _ =
122 let git = try Some (input_line i) with End_of_file -> None in
123 match git with
124 Some x -> gits := x :: !gits; loop()
125 | None -> () in
126 loop ());
127 List.concat
128 (List.map
129 (function l ->
130 List.filter
131 (* all because I don't know how to make a backslash regexp...*)
132 (function x -> String.length x > 10)
133 (Str.split (Str.regexp "[ \t]+") l))
134 !gits)
135
136 let _ =
137 let args = Array.to_list Sys.argv in
138 let file =
139 match args with
140 [_;git_home_info;gits] -> git_home := git_home_info; gits
141 | [_;gits] -> gits
142 | _ -> failwith "args: [git home] git_codes_file" in
143 let codes = get_codes file in
144 let dates = get_dates codes in
145 match List.sort compare dates with
146 (_,last)::prev ->
147 List.iter (function (_,x) -> Printf.printf "%s \\\n" x) (List.rev prev);
148 Printf.printf "%s\n" last
149 | _ -> ()
150
151
152