let analyze_log s =
  let s_date = "\ndate" in
  let s_end = "----------------------------" in
  let re_end = Str.regexp_string s_end in
  let t = Hashtbl.create 37 in
  let rec next_date s pos =
    try
      let (p, field) = get_field s pos s_date in
        let date = date_of_string field in
        try
          let (p2, author) = get_field s p "author" in
          let (p2, state) = get_field s p2 "state" in
          let p3 = String.index_from s p2 '\n' in
          if state = "dead" then
            next_date s p3
          else
            let p4 = Str.search_forward re_end s p3 in
            let comment = String.sub s (p3 + 1) (p4 - p3 - 1) in
            let comment =
              try
                let (p,_) = get_field comment 0 "branches" in
                let p2 = String.index_from comment p '\n' in
                String.sub comment (p2+1) ((String.length comment) - p2 - 1)
              with _ -> comment
            in
            let authors_comments =
              try Hashtbl.find t date
              with Not_found -> []
            in
            let new_l =
              match List.partition (fun (s,_) -> s = author) authors_comments with
                ([], l) -> (author, [comment]) :: l
              | (((a,c)::_), l) ->
                  if List.mem comment c then
                    (a, c) :: l
                  else
                    (a, c @ [comment]) :: l
            in
            Hashtbl.replace t date new_l;
            next_date s p4
      with
        _ ->
          next_date s (p+1)
    with
      Not_found ->
        ()
  in
  let re_sep =
    "\n============================================================================="
  in
  let l = Str.split (Str.regexp_string re_sep) s in
  List.iter (fun s -> next_date s 0) l;
  let l = Hashtbl.fold (fun date l acc -> (date, l) :: acc) t [] in
  List.sort
    (fun(d1,_) (d2,_) -> compare d1 d2)
    l