Meta: Update makem.sh to v0.6-pre

Needed for testing on Emacs 28+.
This commit is contained in:
Adam Porter 2022-12-08 20:37:45 -06:00
parent f22fdd457b
commit 85aee42fae

178
makem.sh
View file

@ -3,11 +3,11 @@
# * makem.sh --- Script to aid building and testing Emacs Lisp packages # * makem.sh --- Script to aid building and testing Emacs Lisp packages
# URL: https://github.com/alphapapa/makem.sh # URL: https://github.com/alphapapa/makem.sh
# Version: 0.3 # Version: 0.6-pre
# * Commentary: # * Commentary:
# makem.sh is a script helps to build, lint, and test Emacs Lisp # makem.sh is a script that helps to build, lint, and test Emacs Lisp
# packages. It aims to make linting and testing as simple as possible # packages. It aims to make linting and testing as simple as possible
# without requiring per-package configuration. # without requiring per-package configuration.
@ -79,7 +79,7 @@ Rules:
Options: Options:
-d, --debug Print debug info. -d, --debug Print debug info.
-h, --help I need somebody! -h, --help I need somebody!
-v, --verbose Increase verbosity, up to -vv. -v, --verbose Increase verbosity, up to -vvv.
--no-color Disable color output. --no-color Disable color output.
--debug-load-path Print load-path from inside Emacs. --debug-load-path Print load-path from inside Emacs.
@ -136,6 +136,27 @@ EOF
echo $file echo $file
} }
function elisp-elint-file {
local file=$(mktemp)
cat >$file <<EOF
(require 'cl-lib)
(require 'elint)
(defun makem-elint-file (file)
(let ((errors 0))
(cl-letf (((symbol-function 'orig-message) (symbol-function 'message))
((symbol-function 'message) (symbol-function 'ignore))
((symbol-function 'elint-output)
(lambda (string)
(cl-incf errors)
(orig-message "%s" string))))
(elint-file file)
;; NOTE: \`errors' is not actually the number of errors, because
;; it's incremented for non-error header strings as well.
(kill-emacs errors))))
EOF
echo "$file"
}
function elisp-checkdoc-file { function elisp-checkdoc-file {
# Since checkdoc doesn't have a batch function that exits non-zero # Since checkdoc doesn't have a batch function that exits non-zero
# when errors are found, we make one. # when errors are found, we make one.
@ -154,7 +175,8 @@ function elisp-checkdoc-file {
": " text))) ": " text)))
(message msg) (message msg)
(setq makem-checkdoc-errors-p t) (setq makem-checkdoc-errors-p t)
(list text start end unfixable))))) ;; Return nil because we *are* generating a buffered list of errors.
nil))))
(mapcar #'checkdoc-file files) (mapcar #'checkdoc-file files)
(when makem-checkdoc-errors-p (when makem-checkdoc-errors-p
(kill-emacs 1)))) (kill-emacs 1))))
@ -165,6 +187,51 @@ EOF
echo $file echo $file
} }
function elisp-byte-compile-file {
# This seems to be the only way to make byte-compilation signal
# errors for warnings AND display all warnings rather than only
# the first one.
local file=$(mktemp)
# TODO: Add file to $paths_temp in other elisp- functions.
paths_temp+=("$file")
cat >"$file" <<EOF
(defun makem-batch-byte-compile (&rest args)
""
(let ((num-errors 0)
(num-warnings 0))
;; NOTE: Only accepts files as args, not directories.
(dolist (file command-line-args-left)
(pcase-let ((\`(,errors ,warnings) (makem-byte-compile-file file)))
(cl-incf num-errors errors)
(cl-incf num-warnings warnings)))
(zerop num-errors)))
(defun makem-byte-compile-file (filename &optional load)
"Call \`byte-compile-warn', returning the number of errors and the number of warnings."
(let ((num-warnings 0)
(num-errors 0))
(cl-letf (((symbol-function 'byte-compile-warn)
(lambda (format &rest args)
;; Copied from \`byte-compile-warn'.
(cl-incf num-warnings)
(setq format (apply #'format-message format args))
(byte-compile-log-warning format t :warning)))
((symbol-function 'byte-compile-report-error)
(lambda (error-info &optional fill &rest args)
(cl-incf num-errors)
;; Copied from \`byte-compile-report-error'.
(setq byte-compiler-error-flag t)
(byte-compile-log-warning
(if (stringp error-info) error-info
(error-message-string error-info))
fill :error))))
(byte-compile-file filename load))
(list num-errors num-warnings)))
EOF
echo "$file"
}
function elisp-check-declare-file { function elisp-check-declare-file {
# Since check-declare doesn't have a batch function that exits # Since check-declare doesn't have a batch function that exits
# non-zero when errors are found, we make one. # non-zero when errors are found, we make one.
@ -200,20 +267,23 @@ Exits non-zero if mis-indented lines are found. Checks files in
(let ((errors-p)) (let ((errors-p))
(cl-labels ((lint-file (file) (cl-labels ((lint-file (file)
(find-file file) (find-file file)
(let ((tick (buffer-modified-tick))) (let ((inhibit-message t))
(let ((inhibit-message t)) (indent-region (point-min) (point-max)))
(indent-region (point-min) (point-max))) (when buffer-undo-list
(when (/= tick (buffer-modified-tick)) ;; Indentation changed: warn for each line.
;; Indentation changed: warn for each line. (dolist (line (undo-lines buffer-undo-list))
(dolist (line (undo-lines buffer-undo-list)) (message "%s:%s: Indentation mismatch" (buffer-name) line))
(message "%s:%s: Indentation mismatch" (buffer-name) line)) (setf errors-p t)))
(setf errors-p t)))) (undo-pos (entry)
(cl-typecase (car entry)
(number (car entry))
(string (abs (cdr entry)))))
(undo-lines (undo-list) (undo-lines (undo-list)
;; Return list of lines changed in UNDO-LIST. ;; Return list of lines changed in UNDO-LIST.
(nreverse (cl-loop for elt in undo-list (nreverse (cl-loop for elt in undo-list
when (and (consp elt) for pos = (undo-pos elt)
(numberp (car elt))) when pos
collect (line-number-at-pos (car elt)))))) collect (line-number-at-pos pos)))))
(mapc #'lint-file (mapcar #'expand-file-name command-line-args-left)) (mapc #'lint-file (mapcar #'expand-file-name command-line-args-left))
(when errors-p (when errors-p
(kill-emacs 1))))) (kill-emacs 1)))))
@ -232,7 +302,6 @@ function elisp-package-initialize-file {
(cons "melpa-stable" "https://stable.melpa.org/packages/"))) (cons "melpa-stable" "https://stable.melpa.org/packages/")))
$elisp_org_package_archive $elisp_org_package_archive
(package-initialize) (package-initialize)
(setq load-prefer-newer t)
EOF EOF
echo $file echo $file
} }
@ -245,6 +314,7 @@ function run_emacs {
local emacs_command=( local emacs_command=(
"${emacs_command[@]}" "${emacs_command[@]}"
-Q -Q
--eval "(setq load-prefer-newer t)"
"${args_debug[@]}" "${args_debug[@]}"
"${args_sandbox[@]}" "${args_sandbox[@]}"
-l $package_initialize_file -l $package_initialize_file
@ -286,8 +356,9 @@ function batch-byte-compile {
[[ $compile_error_on_warn ]] && local error_on_warn=(--eval "(setq byte-compile-error-on-warn t)") [[ $compile_error_on_warn ]] && local error_on_warn=(--eval "(setq byte-compile-error-on-warn t)")
run_emacs \ run_emacs \
--load "$(elisp-byte-compile-file)" \
"${error_on_warn[@]}" \ "${error_on_warn[@]}" \
--funcall batch-byte-compile \ --eval "(unless (makem-batch-byte-compile) (kill-emacs 1))" \
"$@" "$@"
} }
@ -297,10 +368,13 @@ function byte-compile-file {
[[ $compile_error_on_warn ]] && local error_on_warn=(--eval "(setq byte-compile-error-on-warn t)") [[ $compile_error_on_warn ]] && local error_on_warn=(--eval "(setq byte-compile-error-on-warn t)")
# FIXME: Why is the line starting with "&& verbose 3" not indented properly? Emacs insists on indenting it back a level.
run_emacs \ run_emacs \
--load "$(elisp-byte-compile-file)" \
"${error_on_warn[@]}" \ "${error_on_warn[@]}" \
--eval "(byte-compile-file \"$file\")" \ --eval "(pcase-let ((\`(,num-errors ,num-warnings) (makem-byte-compile-file \"$file\"))) (when (or (and byte-compile-error-on-warn (not (zerop num-warnings))) (not (zerop num-errors))) (kill-emacs 1)))" \
|| error "Compiling file failed: $file" && verbose 3 "Compiling $file finished without errors." \
|| { verbose 3 "Compiling file failed: $file"; return 1; }
} }
# ** Files # ** Files
@ -376,7 +450,8 @@ function args-load-files {
# For file in $@, echo "--load $file". # For file in $@, echo "--load $file".
for file in "$@" for file in "$@"
do do
printf -- '--load %q ' "$file" sans_extension=${file%%.el}
printf -- '--load %q ' "$sans_extension"
done done
} }
@ -413,8 +488,7 @@ function ert-tests-p {
} }
function package-main-file { function package-main-file {
# Echo the package's main file. Helpful for setting package-lint-main-file. # Echo the package's main file.
file_pkg=$(git ls-files ./*-pkg.el 2>/dev/null) file_pkg=$(git ls-files ./*-pkg.el 2>/dev/null)
if [[ $file_pkg ]] if [[ $file_pkg ]]
@ -496,6 +570,8 @@ function sandbox {
args_sandbox=( args_sandbox=(
--title "makem.sh: $(basename $(pwd)) (sandbox: $sandbox_dir)" --title "makem.sh: $(basename $(pwd)) (sandbox: $sandbox_dir)"
--eval "(setq user-emacs-directory (file-truename \"$sandbox_dir\"))" --eval "(setq user-emacs-directory (file-truename \"$sandbox_dir\"))"
--load package
--eval "(setq package-user-dir (expand-file-name \"elpa\" user-emacs-directory))"
--eval "(setq user-init-file (file-truename \"$init_file\"))" --eval "(setq user-init-file (file-truename \"$init_file\"))"
) )
@ -658,7 +734,8 @@ function verbose {
if [[ $verbose -ge $1 ]] if [[ $verbose -ge $1 ]]
then then
[[ $1 -eq 1 ]] && local color_name=blue [[ $1 -eq 1 ]] && local color_name=blue
[[ $1 -ge 2 ]] && local color_name=cyan [[ $1 -eq 2 ]] && local color_name=cyan
[[ $1 -ge 3 ]] && local color_name=white
shift shift
log_color $color_name "$@" >&2 log_color $color_name "$@" >&2
@ -706,9 +783,7 @@ function compile-batch {
verbose 2 "Batch-compiling files..." verbose 2 "Batch-compiling files..."
debug "Byte-compile files: ${files_project_byte_compile[@]}" debug "Byte-compile files: ${files_project_byte_compile[@]}"
batch-byte-compile "${files_project_byte_compile[@]}" \ batch-byte-compile "${files_project_byte_compile[@]}"
&& success "Compiling finished without errors." \
|| error "Compilation failed."
} }
function compile-each { function compile-each {
@ -726,9 +801,7 @@ function compile-each {
|| compile_errors=t || compile_errors=t
done done
! [[ $compile_errors ]] \ [[ ! $compile_errors ]]
&& success "Compiling finished without errors." \
|| error "Compilation failed."
} }
function compile { function compile {
@ -738,6 +811,18 @@ function compile {
else else
compile-each "$@" compile-each "$@"
fi fi
local status=$?
if [[ $compile_error_on_warn ]]
then
# Linting: just return status code, because lint rule will print messages.
[[ $status = 0 ]]
else
# Not linting: print messages here.
[[ $status = 0 ]] \
&& success "Compiling finished without errors." \
|| error "Compiling failed."
fi
} }
function batch { function batch {
@ -752,12 +837,15 @@ function batch {
function interactive { function interactive {
# Run Emacs interactively. Most useful with --sandbox and --install-deps. # Run Emacs interactively. Most useful with --sandbox and --install-deps.
local load_file_args=$(args-load-files "${files_project_feature[@]}" "${files_project_test[@]}")
verbose 1 "Running Emacs interactively..." verbose 1 "Running Emacs interactively..."
verbose 2 "Loading files:" "${files_project_feature[@]}" "${files_project_test[@]}" verbose 2 "Loading files: ${load_file_args//--load /}"
[[ $compile ]] && compile
unset arg_batch unset arg_batch
run_emacs \ run_emacs \
$(args-load-files "${files_project_feature[@]}" "${files_project_test[@]}") \ $load_file_args \
--eval "(load user-init-file)" \ --eval "(load user-init-file)" \
"${args_batch_interactive[@]}" "${args_batch_interactive[@]}"
arg_batch="--batch" arg_batch="--batch"
@ -769,6 +857,9 @@ function lint {
lint-checkdoc lint-checkdoc
lint-compile lint-compile
lint-declare lint-declare
# NOTE: Elint doesn't seem very useful at the moment. See comment
# in lint-elint function.
# lint-elint
lint-indent lint-indent
lint-package lint-package
lint-regexps lint-regexps
@ -825,6 +916,28 @@ function lint-elsa {
|| error "Linting with Elsa failed." || error "Linting with Elsa failed."
} }
function lint-elint {
# NOTE: Elint gives a lot of spurious warnings, apparently because it doesn't load files
# that are `require'd, so its output isn't very useful. But in case it's improved in
# the future, and since this wrapper code already works, we might as well leave it in.
verbose 1 "Linting with Elint..."
local errors=0
for file in "${files_project_feature[@]}"
do
verbose 2 "Linting with Elint: $file..."
run_emacs \
--load "$(elisp-elint-file)" \
--eval "(makem-elint-file \"$file\")" \
&& verbose 3 "Linting with Elint found no errors." \
|| { error "Linting with Elint failed: $file"; ((errors++)) ; }
done
[[ $errors = 0 ]] \
&& success "Linting with Elint finished without errors." \
|| error "Linting with Elint failed."
}
function lint-indent { function lint-indent {
verbose 1 "Linting indentation..." verbose 1 "Linting indentation..."
@ -896,7 +1009,8 @@ function test-buttercup {
run_emacs \ run_emacs \
$(args-load-files "${files_project_test[@]}") \ $(args-load-files "${files_project_test[@]}") \
-f buttercup-run \ --load "$buttercup_file" \
--eval "(progn (setq backtrace-on-error-noninteractive nil) (buttercup-run))" \
&& success "Buttercup tests finished without errors." \ && success "Buttercup tests finished without errors." \
|| error "Buttercup tests failed." || error "Buttercup tests failed."
} }