Installs pre-commit hooks for OCaml projects that run dune fmt automatically
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

fix(lint): remove redundant function prefixes (E331)

Strip get_/make_/find_/create_ from 138 function definitions and all
call sites across ocaml-pds, ocaml-pid1, ocaml-precommit,
ocaml-publicsuffix, ocaml-qemu, ocaml-requests, ocaml-retry, and
ocaml-rpmsg. Use Module.v for constructors per the E331 convention.

+36 -35
+7 -9
bin/main.ml
··· 78 78 exit 1 79 79 80 80 let collect_dirs ctx dirs = 81 - let result = 82 - List.concat_map (fun d -> Precommit.find_git_projects ctx d) dirs 83 - in 81 + let result = List.concat_map (fun d -> Precommit.git_projects ctx d) dirs in 84 82 if result = [] then begin 85 83 error "No git repositories found"; 86 84 exit 1 ··· 93 91 let cwd = 94 92 match chdir with None -> Eio.Stdenv.cwd env | Some d -> Eio.Path.(fs / d) 95 93 in 96 - f (Precommit.make_ctx ~cwd ~fs) 94 + f (Precommit.ctx ~cwd ~fs) 97 95 98 96 (* {1 Init command} *) 99 97 ··· 231 229 232 230 (* {1 Check command} *) 233 231 234 - let get_terminal_width () = 232 + let terminal_width () = 235 233 try 236 234 let ic = Unix.open_process_in "tput cols 2>/dev/null" in 237 235 let width = int_of_string (String.trim (input_line ic)) in ··· 244 242 245 243 (* Shared: find AI commits across dirs and display a unified table. 246 244 Returns [(affected_dirs, total_commits, repos_with_issues)]. *) 247 - let find_and_display_ai_commits ctx dirs = 248 - let term_width = get_terminal_width () in 245 + let display_ai_commits ctx dirs = 246 + let term_width = terminal_width () in 249 247 let subject_max = max 20 (term_width - 35) in 250 248 let total_commits = ref 0 in 251 249 let repos_with_issues = ref 0 in ··· 299 297 let check_impl ctx dirs = 300 298 let dirs = collect_dirs ctx dirs in 301 299 let _affected, total_commits, repos_with_issues = 302 - find_and_display_ai_commits ctx dirs 300 + display_ai_commits ctx dirs 303 301 in 304 302 if total_commits > 0 then begin 305 303 error "%d commit%s with AI attribution in %d repo%s" total_commits ··· 357 355 let fix_impl ctx dry_run yes dirs = 358 356 let dirs = collect_dirs ctx dirs in 359 357 let affected, total_commits, repos_with_issues = 360 - find_and_display_ai_commits ctx dirs 358 + display_ai_commits ctx dirs 361 359 in 362 360 if total_commits = 0 then success "No AI attribution found in commit history" 363 361 else if dry_run then begin
+19 -19
lib/precommit.ml
··· 8 8 9 9 type ctx = { cwd : Eio.Fs.dir_ty Eio.Path.t; fs : Eio.Fs.dir_ty Eio.Path.t } 10 10 11 - let make_ctx ~cwd ~fs = 11 + let ctx ~cwd ~fs = 12 12 { cwd :> Eio.Fs.dir_ty Eio.Path.t; fs :> Eio.Fs.dir_ty Eio.Path.t } 13 13 14 14 let pre_commit_hook = ··· 118 118 119 119 (* Find git root by walking up from dir. 120 120 [cwd] is the working directory path, [fs] is the full filesystem. *) 121 - let find_git_root ~cwd ~fs dir = 121 + let git_root ~cwd ~fs dir = 122 122 let _, cwd_path = cwd in 123 123 let base_path = 124 124 if cwd_path = "" || cwd_path = "." then Sys.getcwd () else cwd_path ··· 133 133 then String.sub abs_dir 0 (String.length abs_dir - 2) 134 134 else abs_dir 135 135 in 136 - Log.debug (fun m -> m "find_git_root: dir=%s abs_dir=%s" dir abs_dir); 136 + Log.debug (fun m -> m "git_root: dir=%s abs_dir=%s" dir abs_dir); 137 137 let rec walk path = 138 138 let git_dir = Filename.concat path ".git" in 139 - Log.debug (fun m -> m "find_git_root: checking %s" git_dir); 139 + Log.debug (fun m -> m "git_root: checking %s" git_dir); 140 140 match Eio.Path.kind ~follow:true Eio.Path.(fs / git_dir) with 141 141 | `Not_found -> 142 142 let parent = Filename.dirname path in ··· 155 155 if (not force) && not (file_exists ~fs:ctx.cwd dune_project) then 156 156 Error (Fmt.str "%s: No dune-project found (use --force to override)" dir) 157 157 else 158 - match find_git_root ~cwd:ctx.cwd ~fs:ctx.fs dir with 158 + match git_root ~cwd:ctx.cwd ~fs:ctx.fs dir with 159 159 | None -> Error (Fmt.str "%s: No .git directory found" dir) 160 160 | Some git_root -> 161 161 let git_dir_path = Filename.concat git_root ".git" in ··· 205 205 let formatting_disabled = 206 206 check_formatting_disabled ~fs:ctx.cwd dune_project 207 207 in 208 - match find_git_root ~cwd:ctx.cwd ~fs:ctx.fs dir with 208 + match git_root ~cwd:ctx.cwd ~fs:ctx.fs dir with 209 209 | None -> 210 210 { 211 211 has_pre_commit = false; ··· 248 248 if has_git_here then false 249 249 else 250 250 (* Check if an ancestor has .git *) 251 - match find_git_root ~cwd ~fs dir with 251 + match git_root ~cwd ~fs dir with 252 252 | Some _ -> true 253 253 | None -> false 254 254 255 255 (* Convert absolute path to relative path from cwd_path *) 256 - let make_relative ~cwd_path abs_path = 256 + let relative ~cwd_path abs_path = 257 257 if 258 258 String.length abs_path >= String.length cwd_path 259 259 && String.sub abs_path 0 (String.length cwd_path) = cwd_path ··· 267 267 else rest 268 268 else abs_path 269 269 270 - let rec find_git_projects ctx dir = 270 + let rec git_projects ctx dir = 271 271 let entries = try Eio.Path.read_dir Eio.Path.(ctx.cwd / dir) with _ -> [] in 272 272 let child_path name = if dir = "." then name else Filename.concat dir name in 273 273 (* If dir has .git, include it *) ··· 276 276 let self = 277 277 if self_has_git then [ dir ] 278 278 else if is_inside_git_repo ~cwd:ctx.cwd ~fs:ctx.fs dir then 279 - match find_git_root ~cwd:ctx.cwd ~fs:ctx.fs dir with 279 + match git_root ~cwd:ctx.cwd ~fs:ctx.fs dir with 280 280 | Some git_root -> 281 281 let _, cwd_path = ctx.cwd in 282 282 let cwd_path = 283 283 if cwd_path = "" || cwd_path = "." then Sys.getcwd () else cwd_path 284 284 in 285 - [ make_relative ~cwd_path git_root ] 285 + [ relative ~cwd_path git_root ] 286 286 | None -> [] 287 287 else [] 288 288 in ··· 303 303 |> List.sort String.compare 304 304 |> List.concat_map (fun sub -> 305 305 if file_exists ~fs:ctx.cwd (Filename.concat sub ".git") then [ sub ] 306 - else find_git_projects ctx sub) 306 + else git_projects ctx sub) 307 307 in 308 308 self @ children 309 309 ··· 317 317 let message_has_ai_attribution msg = Re.execp ai_pattern msg 318 318 319 319 (* Get current user's email from git config (local or global) *) 320 - let get_user_email ~fs repo = 320 + let user_email ~fs repo = 321 321 (* First check local repo config *) 322 322 let local_email = 323 323 match Git.Repository.read_config repo with ··· 352 352 353 353 let check_ai_attribution ctx dir = 354 354 Log.debug (fun m -> m "check_ai_attribution: dir=%s" dir); 355 - match find_git_root ~cwd:ctx.cwd ~fs:ctx.fs dir with 355 + match git_root ~cwd:ctx.cwd ~fs:ctx.fs dir with 356 356 | None -> 357 357 Log.debug (fun m -> 358 358 m "check_ai_attribution: no git root found for %s" dir); ··· 361 361 Log.debug (fun m -> m "check_ai_attribution: git_root=%s" git_root); 362 362 (* Use full filesystem for absolute paths *) 363 363 let repo = Git.Repository.open_repo ~fs:ctx.fs (Fpath.v git_root) in 364 - let user_email = get_user_email ~fs:ctx.fs repo in 364 + let user_email = user_email ~fs:ctx.fs repo in 365 365 Log.debug (fun m -> 366 366 m "check_ai_attribution: git_root=%s user_email=%s" git_root 367 367 (Option.value ~default:"<none>" user_email)); ··· 434 434 result) 435 435 436 436 let current_branch ctx dir = 437 - match find_git_root ~cwd:ctx.cwd ~fs:ctx.fs dir with 437 + match git_root ~cwd:ctx.cwd ~fs:ctx.fs dir with 438 438 | None -> None 439 439 | Some git_root -> 440 440 let repo = Git.Repository.open_repo ~fs:ctx.fs (Fpath.v git_root) in 441 441 Git.Repository.current_branch repo 442 442 443 443 let backup_branch ctx dir = 444 - match find_git_root ~cwd:ctx.cwd ~fs:ctx.fs dir with 444 + match git_root ~cwd:ctx.cwd ~fs:ctx.fs dir with 445 445 | None -> failwith (Fmt.str "%s: No .git directory found" dir) 446 446 | Some git_root -> 447 447 let repo = Git.Repository.open_repo ~fs:ctx.fs (Fpath.v git_root) in ··· 464 464 backup_name 465 465 466 466 let rewrite_ai_attribution ctx dir = 467 - match find_git_root ~cwd:ctx.cwd ~fs:ctx.fs dir with 467 + match git_root ~cwd:ctx.cwd ~fs:ctx.fs dir with 468 468 | None -> Error (Fmt.str "%s: No .git directory found" dir) 469 469 | Some git_root -> ( 470 470 let repo = Git.Repository.open_repo ~fs:ctx.fs (Fpath.v git_root) in 471 - let user_email = get_user_email ~fs:ctx.fs repo in 471 + let user_email = user_email ~fs:ctx.fs repo in 472 472 match Git.Repository.head repo with 473 473 | None -> Ok 0 474 474 | Some head_hash ->
+7 -7
lib/precommit.mli
··· 9 9 relative paths and the full filesystem for walking up to parent directories. 10 10 *) 11 11 12 - val make_ctx : cwd:_ Eio.Path.t -> fs:_ Eio.Path.t -> ctx 13 - (** [make_ctx ~cwd ~fs] creates a context from the working directory and full 12 + val ctx : cwd:_ Eio.Path.t -> fs:_ Eio.Path.t -> ctx 13 + (** [ctx ~cwd ~fs] creates a context from the working directory and full 14 14 filesystem paths. *) 15 15 16 16 (** {1 Hook Templates} *) ··· 83 83 val list_subdirs : fs:_ Eio.Path.t -> string -> string list 84 84 (** [list_subdirs ~fs dir] lists subdirectories (excluding hidden ones). *) 85 85 86 - val find_git_projects : ctx -> string -> string list 87 - (** [find_git_projects ctx dir] recursively scans [dir] for directories 88 - containing a [.git] entry. Stops recursing into a directory once a [.git] is 89 - found. Hidden directories are skipped. If [dir] is inside a git repository 90 - (by checking parent directories), it is included even if it doesn't contain 86 + val git_projects : ctx -> string -> string list 87 + (** [git_projects ctx dir] recursively scans [dir] for directories containing a 88 + [.git] entry. Stops recursing into a directory once a [.git] is found. 89 + Hidden directories are skipped. If [dir] is inside a git repository (by 90 + checking parent directories), it is included even if it doesn't contain 91 91 [.git] directly. *) 92 92 93 93 val check_all : ctx -> string list -> (string * hook_status) list
+3
test/test_precommit.mli
··· 1 + (** Pre-commit tests. *) 2 + 1 3 val suite : string * unit Alcotest.test_case list 4 + (** Alcotest suite. *)