(** Repository discovery: bare and non-bare layouts, descriptions, and directory listings. *) open Test_helpers let test_description_missing () = with_temp_file "ogit-description" ".txt" (fun file -> Sys.remove file; Alcotest.(check string) "missing file" Ogit.Resolvers.default_repo_description (Ogit.Resolvers.read_description_file file)) let test_description_empty () = with_temp_file "ogit-description" ".txt" (fun file -> Out_channel.with_open_text file (fun _ -> ()); Alcotest.(check string) "empty file" Ogit.Resolvers.default_repo_description (Ogit.Resolvers.read_description_file file)) let test_description_content () = with_temp_file "ogit-description" ".txt" (fun file -> Out_channel.with_open_text file (fun channel -> output_string channel "A useful repository\n"); Alcotest.(check string) "content" "A useful repository" (Ogit.Resolvers.read_description_file file)) let test_layout_bare () = with_temp_directory "ogit-repos" (fun root -> let bare = Filename.concat root "bare.git" in make_git_directory bare; Alcotest.(check bool) "is_repository" true (Ogit.Resolvers.is_repository bare); match Ogit.Resolvers.repository_layout_or_none bare with | Some { worktree; git_dir } -> Alcotest.(check string) "worktree" bare worktree; Alcotest.(check string) "git_dir" bare git_dir | None -> Alcotest.fail "expected bare layout") let test_layout_non_bare () = with_temp_directory "ogit-repos" (fun root -> let clone = Filename.concat root "clone" in Unix.mkdir clone 0o755; make_git_directory (Filename.concat clone ".git"); Alcotest.(check bool) "is_repository" true (Ogit.Resolvers.is_repository clone); match Ogit.Resolvers.repository_layout_or_none clone with | Some { worktree; git_dir } -> Alcotest.(check string) "worktree" clone worktree; Alcotest.(check string) "git_dir" (Filename.concat clone ".git") git_dir | None -> Alcotest.fail "expected non-bare layout") let test_layout_not_a_repo () = with_temp_directory "ogit-repos" (fun root -> let directory = Filename.concat root "not-a-repository" in Unix.mkdir directory 0o755; Alcotest.(check bool) "not a repository" false (Ogit.Resolvers.is_repository directory)) let test_layout_non_bare_with_shadowing_files () = with_temp_directory "ogit-repos" (fun root -> let repo = Filename.concat root "TAOH" in Unix.mkdir repo 0o755; make_git_directory (Filename.concat repo ".git"); (* Create HEAD file and objects/ directory in the worktree that could confuse bare-repository detection. *) Out_channel.with_open_text (Filename.concat repo "HEAD") (fun ch -> output_string ch "ref: refs/heads/master\n"); Unix.mkdir (Filename.concat repo "objects") 0o755; Alcotest.(check bool) "is_repository" true (Ogit.Resolvers.is_repository repo); match Ogit.Resolvers.repository_layout_or_none repo with | Some { worktree; git_dir } -> Alcotest.(check string) "worktree" repo worktree; Alcotest.(check string) "git_dir uses .git" (Filename.concat repo ".git") git_dir | None -> Alcotest.fail "expected non-bare layout") let test_listing () = with_temp_directory "ogit-listing" (fun root -> make_git_directory (Filename.concat root "visible.git"); make_git_directory (Filename.concat root ".hidden.git"); let config = Ogit.Config.{ default with git_project_root = root } in match Ogit.Resolvers.repositories config with | Ok repositories -> Alcotest.(check (list string)) "visible only" [ "visible.git" ] repositories | Error error -> Alcotest.failf "%a" Ogit.Resolvers.pp_error error) let test_fallback_branches () = let config = Ogit.Config.{ default with default_branch = "trunk" } in Alcotest.(check (list string)) "trunk first" [ "trunk"; "main"; "master" ] (Ogit.Resolvers.fallback_branch_candidates config); let main = Ogit.Config.{ config with default_branch = "main" } in Alcotest.(check (list string)) "main deduped" [ "main"; "master" ] (Ogit.Resolvers.fallback_branch_candidates main) let suite = ( "repository discovery", [ Alcotest.test_case "description missing" `Quick test_description_missing; Alcotest.test_case "description empty" `Quick test_description_empty; Alcotest.test_case "description content" `Quick test_description_content; Alcotest.test_case "bare layout" `Quick test_layout_bare; Alcotest.test_case "non-bare layout" `Quick test_layout_non_bare; Alcotest.test_case "non-bare with shadowing files" `Quick test_layout_non_bare_with_shadowing_files; Alcotest.test_case "not a repository" `Quick test_layout_not_a_repo; Alcotest.test_case "listing" `Quick test_listing; Alcotest.test_case "fallback branches" `Quick test_fallback_branches; ] )