let diff_file ?rev ?rev2 file =
  let dir = Filename.dirname file in
  let f = Filename.basename file in
  let temp_file = Filename.temp_file "ocamlcvs" "diff" in
  let com = "cd "^(Filename.quote dir)^" ; cvs -f diff "^
    (match rev with
      None -> ""
    | Some r -> " -r "^(Ocvs_revision.string_of_revision_number r.rev_number)^" ")^
    (match rev2 with
      None -> ""
    | Some r -> " -r "^(Ocvs_revision.string_of_revision_number r.rev_number)^" ")^
    (Filename.quote f)^" > "^temp_file
  in
  begin
    match Sys.command com with
      0 -> ()
    | n ->
        delete_file temp_file;
        raise (Ocvs_types.CvsFailure (Ocvs_messages.error_exec com))
  end;
  let s = input_file_as_string temp_file in
  (* we must remove some cvs information (5 or 6 lines) to get only the diffs *)
  let s2 = remove_n_first_lines
      (match rev with None -> 5 | Some _ -> 6)
      s
  in
  try
     (* get the rcs archive name *)
    let rcs_file =
      try
        let s_rcs = "RCS file: " in
        let i1 = (Str.search_forward (Str.regexp_string s_rcs) s 0) + (String.length s_rcs) in
        let i2 = String.index_from s i1 '\n' in
        String.sub s i1 (i2 - i1)
      with
        Not_found ->
          raise (Failure Ocvs_messages.error_rcs_archive)
    in
    let l = Odiff.from_string s2 in
    delete_file temp_file ;
    (l, rcs_file)
  with
    Failure s ->
      delete_file temp_file ;
      raise (Failure s)