Release coccinelle-0.2.0rc1
[bpt/coccinelle.git] / tools / gitsort.ml
1 (* sort a list of git codes such that the most recent comes first *)
2
3 let git_home = ref "/home/julia/linux-2.6"
4
5 let unwind_protect f cleanup =
6 try f ()
7 with e -> begin cleanup e; raise e end
8
9 let (with_open_infile: string -> ((in_channel) -> 'a) -> 'a) = fun file f ->
10 let chan = open_in file in
11 unwind_protect (fun () ->
12 let res = f chan in
13 close_in chan;
14 res)
15 (fun e -> close_in chan)
16
17 (* ----------------------------------------------------------------------- *)
18
19 let months =
20 [("Jan",1);("Feb",2);("Mar",3);("Apr",4);("May",5);("Jun",6);("Jul",7);
21 ("Aug",8);("Sep",9);("Oct",10);("Nov",11);("Dec",12)]
22
23 let antimonths =
24 [(1,31);(2,28);(3,31);(4,30);(5,31); (6,30);(7,31);(8,31);(9,30);(10,31);
25 (11,30);(12,31);(0,31)]
26
27 let normalize (year,month,day,hour,minute,second) =
28 if hour < 0
29 then
30 let (day,hour) = (day - 1,hour + 24) in
31 if day = 0
32 then
33 let month = month - 1 in
34 let day = List.assoc month antimonths in
35 let day =
36 if month = 2 && year / 4 * 4 = year && not (year / 100 * 100 = year)
37 then 29
38 else day in
39 if month = 0
40 then (year-1,12,day,hour,minute,second)
41 else (year,month,day,hour,minute,second)
42 else (year,month,day,hour,minute,second)
43 else (year,month,day,hour,minute,second)
44
45 exception Fail of string
46
47 let read_info code =
48 let _ =
49 Sys.command
50 (Printf.sprintf
51 "pushd %s >& /dev/null ; git log %s^..%s | grep Date: > /tmp/gitsort_info ; popd >& /dev/null"
52 !git_home code code) in
53 with_open_infile "/tmp/gitsort_info" (fun i ->
54 let l =
55 try input_line i
56 with End_of_file -> raise (Fail "bad git file") in
57 match Str.split (Str.regexp " ") l with
58 [date;_;_;weekday;month;day;time;year;offset] ->
59 let day = int_of_string day in
60 let month = List.assoc month months in
61 let year = int_of_string year in
62 (match Str.split (Str.regexp ":") time with
63 [hour;minute;second] ->
64 let hour = int_of_string hour in
65 let minute = int_of_string minute in
66 let second = int_of_string second in
67 let modifier =
68 match String.get offset 0 with
69 '-' -> -1
70 | '+' -> 1
71 | _ -> raise (Fail "bad offset") in
72 (if not (String.sub offset 3 2 = "00")
73 then raise (Fail "require 0 minutes difference"));
74 let hour =
75 hour + (modifier * (int_of_string (String.sub offset 1 2))) in
76 normalize (year,month,day,hour,minute,second)
77 | _ -> raise (Fail "bad date2"))
78 | l -> raise (Fail ("bad date1: "^(String.concat "|" l))))
79
80 let rec get_dates = function
81 [] -> []
82 | code::rest ->
83 let date =
84 try Some (read_info code)
85 with
86 Fail s -> Printf.printf "problem in %s: %s\n" code s; None
87 | _ -> Printf.printf "problem in %s\n" code; None in
88 match date with
89 Some date -> (date,code)::(get_dates rest)
90 | None -> get_dates rest
91
92 let get_codes file =
93 let gits = ref ([] : string list) in
94 with_open_infile file (fun i ->
95 let rec loop _ =
96 let git = try Some (input_line i) with End_of_file -> None in
97 match git with
98 Some x -> gits := x :: !gits; loop()
99 | None -> () in
100 loop ());
101 List.concat
102 (List.map
103 (function l ->
104 List.filter
105 (* all because I don't know how to make a backslash regexp...*)
106 (function x -> String.length x > 10)
107 (Str.split (Str.regexp "[ \t]+") l))
108 !gits)
109
110 let _ =
111 let args = Array.to_list Sys.argv in
112 let file =
113 match args with
114 [_;git_home_info;gits] -> git_home := git_home_info; gits
115 | [_;gits] -> gits
116 | _ -> failwith "args: [git home] git_codes_file" in
117 let codes = get_codes file in
118 let dates = get_dates codes in
119 match List.sort compare dates with
120 (_,last)::prev ->
121 List.iter (function (_,x) -> Printf.printf "%s \\\n" x) (List.rev prev);
122 Printf.printf "%s\n" last
123 | _ -> ()
124
125
126