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