dev: fix and refactor commit lint rules

- Fix rules that weren't working due to faulty logic.
- Revise linter messages for clarity and concision.
- Use conventional commit nomenclature: summary -> subject
- case-fold-search = nil, to ensure case sensitive searches
- Exclude bump type from length checks
This commit is contained in:
Henrik Lissner 2021-08-01 15:40:45 -04:00
parent 11a0c0cbdb
commit 5df31a4895

View file

@ -32,11 +32,11 @@
;;; Git hooks ;;; Git hooks
(defvar doom-cli-commit-rules (defvar doom-cli-commit-rules
(list (cons "^[^\n]\\{10,\\}\n" (list (cons "^[^\n]\\{10,\\}$"
"Commit summary is too short (<10) and should be more descriptive") "Subject is too short (<10) and should be more descriptive")
(cons "^\\(revert!?:[^\n]\\{,72\\}\\|[^\n]\\{,80\\}\\)\n" (cons "^\\(\\(revert\\|bump\\)!?: \\|[^\n]\\{,80\\}\\)$"
"Commit summary too long; <=72 is ideal, 80 is max") "Subject too long; <=72 is ideal, 80 is max")
(cons (concat (cons (concat
"^\\(" "^\\("
@ -54,23 +54,24 @@
(cons (lambda () (cons (lambda ()
(looking-at "^\\(bump\\|revert\\|release\\|merge\\|module\\)!?([^)]+):")) (looking-at "^\\(bump\\|revert\\|release\\|merge\\|module\\)!?([^)]+):"))
"This commit type's scope goes after the colon, not before") "This type's scope goes after the colon, not before")
(cons (lambda () (cons (lambda ()
(when (looking-at "[^ :!(]+!?(\\([^)]+\\)): ") (when (looking-at "[^ :!(]+!?(\\([^)]+\\)): ")
(not (not
(string-match (cl-loop with scopes =
(string-join
(cons (concat
"^" (regexp-opt
(cl-loop for path (cl-loop for path
in (cdr (doom-module-load-path (list doom-modules-dir))) in (cdr (doom-module-load-path (list doom-modules-dir)))
for (_category . module) for (_category . module)
= (doom-module-from-path path) = (doom-module-from-path path)
collect (symbol-name module))) "$") collect (symbol-name module))
with scopes-re =
(string-join (cons (concat "^" (regexp-opt scopes) "$")
'("^&" "^cli$")) '("^&" "^cli$"))
"\\|") "\\|")
(match-string 1))))) for scope in (split-string (match-string 1) ",")
if (string-match scopes-re scope)
return t))))
"Invalid scope") "Invalid scope")
(cons (lambda () (cons (lambda ()
@ -102,7 +103,7 @@
nil t)) nil t))
"Use present tense/imperative voice for footer references, without a colon") "Use present tense/imperative voice for footer references, without a colon")
;; TODO Check that bump/revert SUMMARY list: 1) valid modules and 2) ;; TODO Check that bump/revert SUBJECT list: 1) valid modules and 2)
;; modules whose files are actually being touched. ;; modules whose files are actually being touched.
;; TODO Ensure your diff corraborates your SCOPE ;; TODO Ensure your diff corraborates your SCOPE
@ -136,45 +137,51 @@
;;; ;;;
(defun doom-cli--ci-lint-commits (from &optional to) (defun doom-cli--ci-lint-commits (from &optional to)
(let ((errors? 0)
commits
case-fold-search)
(with-temp-buffer (with-temp-buffer
(save-excursion
(insert (insert
(cdr (doom-call-process (cdr (doom-call-process
"git" "log" "git" "log"
(format "%s...%s" from (or to "HEAD")))))) (format "%s...%s" from (or to "HEAD")))))
(while (re-search-forward "^commit \\([a-z0-9]\\{40\\}\\)" nil t) (while (re-search-backward "^commit \\([a-z0-9]\\{40\\}\\)" nil t)
(let ((commit (match-string 1)) (push (cons (match-string 1)
errors) (replace-regexp-in-string
(forward-line 4) "^ " ""
(save-restriction
(save-match-data
(narrow-to-region
(point) (save-excursion
(if (re-search-forward "^commit \\([a-z0-9]\\{40\\}\\)" nil t)
(match-beginning 0)
(point-max))))
(indent-rigidly (point-min) (point-max) -4))
(save-excursion (save-excursion
(print! (start "Commit %s") commit) (buffer-substring-no-properties
(search-forward "\n\n")
(if (re-search-forward "\ncommit \\([a-z0-9]\\{40\\}\\)" nil t)
(match-beginning 0)
(point-max))))))
commits)))
(dolist (commit commits)
(let (errors)
(with-temp-buffer
(save-excursion (insert (cdr commit)))
(dolist (rule doom-cli-commit-rules) (dolist (rule doom-cli-commit-rules)
(cl-destructuring-bind (pred . msg) rule (save-excursion
(goto-char (point-min))
(save-match-data (save-match-data
(when (if (functionp pred) (cl-destructuring-bind (pred . msg) rule
(funcall pred) (and (cond ((functionp pred)
(if (stringp pred) (funcall pred))
(not (re-search-forward pred nil t)) ((stringp pred)
(error "Invalid predicate: %S" pred))) (not (re-search-forward pred nil t)))
(push msg (alist-get commit errors nil nil #'equal))))))) ((error "Invalid predicate: %S" pred)))
(when errors (push msg errors))))))
(dolist (error (reverse errors)) (if (not errors)
(print! (error "Commit %s") (car error)) (print! (success "Commit %s") (car commit))
(cl-incf errors?)
(print! (error "Commit %s") (car commit))
(print-group! (print-group!
(dolist (e (reverse (cdr error))) (print! "%S" (cdr commit))
(print! (info e))))) (dolist (e (reverse errors))
(print! (error "%s" e))))))))
(when (> errors? 0)
(terpri) (terpri)
(print! "%d commit(s) failed the linter" (length errors)) (print! "%d commit(s) failed the linter" errors?)
(terpri) (terpri)
(print! "See https://doomemacs.org/project.org#commit-message-formatting for details") (print! "See https://doomemacs.org/project.org#commit-message-formatting for details")
(throw 'exit 1))))) (throw 'exit 1)))
t)) t)