(** Resolving paths within a Git tree, including unreachable objects. *) open Test_helpers let test_root_tree () = with_temp_directory "ogit-paths" (fun root -> let name = "project" in let path = Filename.concat root name in Unix.mkdir path 0o755; ignore (git [ "-C"; path; "init"; "-q"; "-b"; "main" ]); ignore (git [ "-C"; path; "config"; "user.name"; "Test" ]); ignore (git [ "-C"; path; "config"; "user.email"; "t@t.invalid" ]); Out_channel.with_open_text (Filename.concat path "file.txt") (fun ch -> output_string ch "data\n"); ignore (git [ "-C"; path; "add"; "." ]); ignore (git [ "-C"; path; "commit"; "-q"; "-m"; "init" ]); let root_tree = git [ "-C"; path; "rev-parse"; "HEAD^{tree}" ] in let config = Ogit.Config.{ default with git_project_root = root } in let repository = match Lwt_main.run (Ogit.Resolvers.open_repository config name) with | Ok r -> r | Error e -> Alcotest.failf "%a" Ogit.Resolvers.pp_error e in Fun.protect ~finally:(fun () -> Lwt_main.run (Ogit.Resolvers.close_repository repository)) (fun () -> match Lwt_main.run (Ogit.Resolvers.Tree.find_path repository root_tree) with | Ok trail -> Alcotest.(check (list (pair string string))) "empty trail" [] trail | Error e -> Alcotest.failf "%a" Ogit.Resolvers.pp_error e)) let test_nested () = with_temp_directory "ogit-paths" (fun root -> let name = "project" in let path = Filename.concat root name in Unix.mkdir path 0o755; ignore (git [ "-C"; path; "init"; "-q"; "-b"; "main" ]); ignore (git [ "-C"; path; "config"; "user.name"; "Test" ]); ignore (git [ "-C"; path; "config"; "user.email"; "t@t.invalid" ]); let dir = Filename.concat path "dir" in Unix.mkdir dir 0o755; Out_channel.with_open_text (Filename.concat dir "nested.txt") (fun ch -> output_string ch "nested\n"); ignore (git [ "-C"; path; "add"; "." ]); ignore (git [ "-C"; path; "commit"; "-q"; "-m"; "init" ]); let nested_tree = git [ "-C"; path; "rev-parse"; "HEAD:dir" ] in let nested_blob = git [ "-C"; path; "rev-parse"; "HEAD:dir/nested.txt" ] in let config = Ogit.Config.{ default with git_project_root = root } in let repository = match Lwt_main.run (Ogit.Resolvers.open_repository config name) with | Ok r -> r | Error e -> Alcotest.failf "%a" Ogit.Resolvers.pp_error e in Fun.protect ~finally:(fun () -> Lwt_main.run (Ogit.Resolvers.close_repository repository)) (fun () -> match Lwt_main.run (Ogit.Resolvers.Tree.find_path repository nested_blob) with | Ok trail -> Alcotest.(check (list (pair string string))) "nested trail" [ ("dir", nested_tree); ("nested.txt", nested_blob) ] trail | Error e -> Alcotest.failf "%a" Ogit.Resolvers.pp_error e)) let test_unreachable () = with_temp_directory "ogit-paths" (fun root -> let name = "project" in let path = Filename.concat root name in Unix.mkdir path 0o755; ignore (git [ "-C"; path; "init"; "-q"; "-b"; "main" ]); ignore (git [ "-C"; path; "config"; "user.name"; "Test" ]); ignore (git [ "-C"; path; "config"; "user.email"; "t@t.invalid" ]); Out_channel.with_open_text (Filename.concat path "file.txt") (fun ch -> output_string ch "data\n"); ignore (git [ "-C"; path; "add"; "." ]); ignore (git [ "-C"; path; "commit"; "-q"; "-m"; "init" ]); let dangling_file = Filename.concat root "dangling.txt" in Out_channel.with_open_text dangling_file (fun ch -> output_string ch "dangling\n"); let dangling_blob = git [ "-C"; path; "hash-object"; "-w"; dangling_file ] in let config = Ogit.Config.{ default with git_project_root = root } in let repository = match Lwt_main.run (Ogit.Resolvers.open_repository config name) with | Ok r -> r | Error e -> Alcotest.failf "%a" Ogit.Resolvers.pp_error e in Fun.protect ~finally:(fun () -> Lwt_main.run (Ogit.Resolvers.close_repository repository)) (fun () -> match Lwt_main.run (Ogit.Resolvers.Tree.find_path repository dangling_blob) with | Error (Ogit.Resolvers.Not_found _) -> () | Error e -> Alcotest.failf "%a" Ogit.Resolvers.pp_error e | Ok _ -> Alcotest.fail "unreachable object should return Not_found")) let suite = ( "tree paths", [ Alcotest.test_case "root tree" `Slow test_root_tree; Alcotest.test_case "nested path" `Slow test_nested; Alcotest.test_case "unreachable object" `Slow test_unreachable; ] )