#!/usr/bin/env ocaml
open Printf

let run fmt =
  ksprintf (fun cmd ->
      printf "+ %s\n%!" cmd;
      let i = Sys.command cmd in
      if i <> 0 then (
        Printf.eprintf "\027[31mERROR %d\027[0m\n" i;
        exit i
      )
    ) fmt

let git_daemon dir =
  Sys.chdir dir;
  run "git daemon --base-path=. --export-all \
       --enable=receive-pack --reuseaddr \
       --informative-errors --verbose"

let git_add file =
  run "git add %s" file

let git_commit msg =
  run "git commit -a -m %S" msg

let rmdir dir =
  run "rm -rf %s" dir

let mkdir = function
  | ""
  | "." -> ()
  | dir -> run "mkdir -p %s" dir

let cat (file, contents) =
  mkdir (Filename.dirname file);
  run "echo %S > %s" contents file

let git_init dir files =
  mkdir dir;
  let cwd = Sys.getcwd () in
  Sys.chdir dir;
  run "git init";
  List.iter cat files;
  List.iter (fun (file, _) ->
      git_add file
    ) files;
  git_commit "Initial commit";
  run "git config --bool core.bare true";
  Sys.chdir cwd

let files =
  [ "foo", "foo";
    "x/y", "bar"; ]

let (/) = Filename.concat
let tmp = Filename.temp_dir_name

let () = Random.self_init ()

let random_string len =
  let gen () = match Random.int (26 + 26 + 10) with
    | n when n < 26 -> int_of_char 'a' + n
    | n when n < 26 + 26 -> int_of_char 'A' + n - 26
    | n -> int_of_char '0' + n - 26 - 26
  in
  let gen () = char_of_int (gen ()) in

  Bytes.create len |> fun raw ->
  for i = 0 to len - 1 do Bytes.set raw i (gen ()) done;
  Bytes.unsafe_to_string raw

let () =
  let repo = tmp / "ocaml-git" / (random_string 3) in
  rmdir repo;
  git_init repo files;
  git_daemon repo
