<commit_before>(* Does this work on CygWin? *)
open Unix 

type diff = {original_file: string; new_file: string; original_method_name: string; new_method_name: string}

let buff_size = 1024

let execProgram (program: string) (callArray : string array) =
    let git_in = openfile "/dev/null" [O_RDONLY] 0o640 in
    let (fd_in, fd_out) = pipe () in
    let args = callArray in
    (* git should output to fdin *)
    let _ = create_process program args git_in fd_out fd_out in
    close fd_out;
    let input = in_channel_of_descr fd_in in 
    let gitOutput = Buffer.create buff_size in
    (* Read file until end *)
    try
        while true do         
            let line = input_char input in
            Buffer.add_char gitOutput line 
        done;
        assert false;
    with End_of_file -> 
        Buffer.contents gitOutput;;

let execGit (callArray : string array) =
    execProgram "git" callArray

let runGitDiff () =
    let args = [| "git"; "diff"; "-U0"; "@{1}" |] in
    execGit args

(* white space characters, according to https://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html, except \f *)
let whiteSpace = "[ \t\n\x0B\r]"

let diff_to_function_list output =
    let functionNames = ref [] in
    let regex = Str.regexp ("@@.*@@[^(]*\\b\\([a-zA-Z]+\\)" ^ whiteSpace ^ "*(?+.*") in
    let index = ref 0 in
    try 
        while true do 
        let _ = Str.search_forward regex output !index in
        index := Str.match_end ();
        functionNames := (Str.matched_group 1 output) :: !functionNames;
        done; 
        assert false;
    with Not_found ->
        !functionNames

(* Problem with using git log -L:<func_name>:<file> might be that it does not consider changes in the working tree *)
let check_log functionName fileName = 
    let args = [| "git"; "log"; "-L:"^functionName^ ":" ^fileName|] in
    execGit args

let is_clean (directory: string) = 
    let args = [|"git"; "diff"; "^HEAD"; "-C"; directory|] in
    let diff = execGit args in
    0 = String.length diff 

let last_commit_id (directory: string) = 
    let args = [|"git"; "-C"; directory; "rev-parse"; "HEAD"; |] in
    let output = execGit args in
    String.trim output

let current_commit (directory: string) = 
    if is_clean directory then Some (last_commit_id directory)
    else None

let may f opt = match opt with
    Some x -> f x |
    None -> ()

let git_log dir = 
    let args = [|"git"; "-C"; dir ; "log"; "--pretty=format:%H" |] in
    execGit args

let () = may print_endline (current_commit ".")

let run () = 
    let gitOutput = runGitDiff () in 
    print_string gitOutput;
    let found = diff_to_function_list gitOutput in
    print_endline "The following functions were changed:";
    print_endline (String.concat "\n" found);<commit_msg>Fix check whether src dir is clean<commit_after>(* Does this work on CygWin? *)
open Unix 

type diff = {original_file: string; new_file: string; original_method_name: string; new_method_name: string}

let buff_size = 1024

let execProgram (program: string) (callArray : string array) =
    let git_in = openfile "/dev/null" [O_RDONLY] 0o640 in
    let (fd_in, fd_out) = pipe () in
    let args = callArray in
    (* git should output to fdin *)
    let _ = create_process program args git_in fd_out fd_out in
    close fd_out;
    let input = in_channel_of_descr fd_in in 
    let gitOutput = Buffer.create buff_size in
    (* Read file until end *)
    try
        while true do         
            let line = input_char input in
            Buffer.add_char gitOutput line 
        done;
        assert false;
    with End_of_file -> 
        Buffer.contents gitOutput;;

let execGit (callArray : string array) =
    execProgram "git" callArray

let runGitDiff () =
    let args = [| "git"; "diff"; "-U0"; "@{1}" |] in
    execGit args

(* white space characters, according to https://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html, except \f *)
let whiteSpace = "[ \t\n\x0B\r]"

let diff_to_function_list output =
    let functionNames = ref [] in
    let regex = Str.regexp ("@@.*@@[^(]*\\b\\([a-zA-Z]+\\)" ^ whiteSpace ^ "*(?+.*") in
    let index = ref 0 in
    try 
        while true do 
        let _ = Str.search_forward regex output !index in
        index := Str.match_end ();
        functionNames := (Str.matched_group 1 output) :: !functionNames;
        done; 
        assert false;
    with Not_found ->
        !functionNames

(* Problem with using git log -L:<func_name>:<file> might be that it does not consider changes in the working tree *)
let check_log functionName fileName = 
    let args = [| "git"; "log"; "-L:"^functionName^ ":" ^fileName|] in
    execGit args

let is_clean (directory: string) = 
    let args = [|"git"; "-C"; directory; "diff"; "^HEAD";|] in
    let diff = execGit args in
    0 = String.length diff 

let last_commit_id (directory: string) = 
    let args = [|"git"; "-C"; directory; "rev-parse"; "HEAD"; |] in
    let output = execGit args in
    String.trim output

let current_commit (directory: string) = 
    if is_clean directory then Some (last_commit_id directory)
    else None

let may f opt = match opt with
    Some x -> f x |
    None -> ()

let git_log dir = 
    let args = [|"git"; "-C"; dir ; "log"; "--pretty=format:%H" |] in
    execGit args

let run () = 
    let gitOutput = runGitDiff () in 
    print_string gitOutput;
    let found = diff_to_function_list gitOutput in
    print_endline "The following functions were changed:";
    print_endline (String.concat "\n" found);
{'fraction_non_alphanumeric': 0.12083558436880966, 'fraction_numerical': 0.005402485143165856, 'mean_word_length': 2.79890560875513, 'pattern_counts': {'":': 2, '<': 7, '<?xml version=': 0, '>': 15, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2173487', 'n_tokens_mistral': 1826, 'n_tokens_neox': 1751, 'n_words': 597}