[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/plz b77283748b 31/81: Meta: Update makem.sh
From: |
ELPA Syncer |
Subject: |
[elpa] externals/plz b77283748b 31/81: Meta: Update makem.sh |
Date: |
Wed, 11 May 2022 17:57:59 -0400 (EDT) |
branch: externals/plz
commit b77283748b212f32dec9aa17feec2093aace6c33
Author: Adam Porter <adam@alphapapa.net>
Commit: Adam Porter <adam@alphapapa.net>
Meta: Update makem.sh
---
.github/workflows/test.yml | 16 +-
Makefile | 13 +-
makem.sh | 626 ++++++++++++++++++++++++++++++++++-----------
3 files changed, 495 insertions(+), 160 deletions(-)
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 11428d808e..b3c22ed9dc 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -47,21 +47,19 @@ jobs:
- uses: actions/checkout@v2
- - name: Install sandbox script
- run: |
- curl -o $GITHUB_WORKSPACE/emacs-sandbox.sh \
-
https://raw.githubusercontent.com/alphapapa/emacs-sandbox.sh/master/emacs-sandbox.sh
- chmod +x $GITHUB_WORKSPACE/emacs-sandbox.sh
- echo ::add-path::$GITHUB_WORKSPACE
- echo ::set-env name=SANDBOX_DIR::$(mktemp -d)
-
- name: Initialize sandbox
- run: ./makem.sh -vv --sandbox-dir=$SANDBOX_DIR --auto-install --install
package-lint
+ run: |
+ SANDBOX_DIR=$(mktemp -d) || exit 1
+ echo ::set-env name=SANDBOX_DIR::$SANDBOX_DIR
+ ./makem.sh -vv --sandbox-dir=$SANDBOX_DIR --install-deps
--install-linters
# The "all" rule is not used, because it treats compilation warnings
# as failures, so linting and testing are run as separate steps.
- name: Lint
+ # NOTE: Uncomment this line to treat lint failures as passing
+ # so the job doesn't show failure.
+ # continue-on-error: true
run: ./makem.sh -vv --sandbox-dir=$SANDBOX_DIR lint
- name: Test
diff --git a/Makefile b/Makefile
index 5000738761..1ca3da4b8e 100644
--- a/Makefile
+++ b/Makefile
@@ -1,3 +1,7 @@
+# * makem.sh/Makefile --- Script to aid building and testing Emacs Lisp
packages
+
+# This Makefile is from the makem.sh repo:
<https://github.com/alphapapa/makem.sh>.
+
# * Arguments
# For consistency, we use only var=val options, not hyphen-prefixed options.
@@ -7,8 +11,11 @@
# conflict with Make's own arguments through Make to the script.
# Using -- doesn't seem to do it.
-ifdef auto-install
- AUTO_INSTALL = "--auto-install"
+ifdef install-deps
+ INSTALL_DEPS = "--install-deps"
+endif
+ifdef install-linters
+ INSTALL_LINTERS = "--install-linters"
endif
ifdef sandbox
@@ -42,4 +49,4 @@ endif
# directory by that name exists, which can confuse Make.
%:
- @./makem.sh $(DEBUG) $(VERBOSE) $(SANDBOX) $(SANDBOX_DIR)
$(AUTO_INSTALL) $(@)
+ @./makem.sh $(DEBUG) $(VERBOSE) $(SANDBOX) $(SANDBOX_DIR)
$(INSTALL_DEPS) $(INSTALL_LINTERS) $(@)
diff --git a/makem.sh b/makem.sh
index 40c49c5a2b..060bf19f15 100755
--- a/makem.sh
+++ b/makem.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/usr/bin/env bash
# * makem.sh --- Script to aid building and testing Emacs Lisp packages
@@ -21,13 +21,11 @@
# occur. With increasing verbosity levels, more detail gives positive
# feedback. Output is colored by default to make reading easy.
-# When desired, emacs-sandbox.sh can be used as a backend, which
-# allows package dependencies to be installed automatically into a
-# clean Emacs "sandbox" configuration without affecting the
-# developer's personal configuration. This is especially helpful when
+# The script can run Emacs with the developer's local Emacs
+# configuration, or with a clean, "sandbox" configuration that can be
+# optionally removed afterward. This is especially helpful when
# upstream dependencies may have released new versions that differ
-# from those installed in the developer's personal configuration. See
-# <https://github.com/alphapapa/emacs-sandbox.sh>.
+# from those installed in the developer's personal configuration.
# * License:
@@ -50,46 +48,60 @@ function usage {
cat <<EOF
$0 [OPTIONS] RULES...
+Linter- and test-specific rules will error when their linters or tests
+are not found. With -vv, rules that run multiple rules will show a
+message for unavailable linters or tests.
+
Rules:
all Run all lints and tests.
compile Byte-compile source files.
- lint Run all lints.
+ lint Run all linters, ignoring unavailable ones.
lint-checkdoc Run checkdoc.
lint-compile Byte-compile source files with warnings as errors.
+ lint-declare Run check-declare.
+ lint-indent Lint indentation.
lint-package Run package-lint.
+ lint-regexps Run relint.
+
+ test, tests Run all tests, ignoring missing test types.
+ test-buttercup Run Buttercup tests.
+ test-ert Run ERT tests.
+ test-ert-interactive Run ERT tests interactively.
- test, tests Run all tests.
- test-buttercup Run Buttercup tests.
- test-ert Run ERT tests.
+ batch Run Emacs in batch mode, loading project source and test files
+ automatically, with remaining args (after "--") passed to Emacs.
+ interactive Run Emacs interactively, loading project source and test files
+ automatically, with remaining args (after "--") passed to Emacs.
Options:
-d, --debug Print debug info.
-h, --help I need somebody!
-v, --verbose Increase verbosity, up to -vv.
- --debug-load-path Print load-path.
- -f FILE, --file FILE Check FILE in addition to discovered files.
+ --debug-load-path Print load-path from inside Emacs.
+
+ -E, --emacs PATH Run Emacs at PATH.
+
+ -e, --exclude FILE Exclude FILE from linting and testing.
+ -f, --file FILE Check FILE in addition to discovered files.
--no-color Disable color output.
-C, --no-compile Don't compile files automatically.
Sandbox options:
- These require emacs-sandbox.sh to be on your PATH. Find it at
- <https://github.com/alphapapa/emacs-sandbox.sh>.
-
- -s, --sandbox Run Emacs with emacs-sandbox.sh in a temporary
- directory (removing directory on exit).
- -S, --sandbox-dir DIR Use DIR for the sandbox directory (leaving it
- on exit). Implies -s.
- --auto-install Automatically install package dependencies.
+ -s, --sandbox Run Emacs with an empty config in a temporary
+ sandbox directory (removing directory on exit).
+ -S, --sandbox-dir DIR Run Emacs with DIR as persistent sandbox directory.
+ Makes an Emacs version-specific subdirectory, which
+ facilitates testing under multiple Emacs versions.
+ --install-deps Automatically install package dependencies.
+ --install-linters Automatically install linters.
-i, --install PACKAGE Install PACKAGE before running rules.
Source files are automatically discovered from git, or may be
-specified with options.
-
-Package dependencies are discovered from "Package-Requires" headers in
-source files and from a Cask file.
+specified with options. Package dependencies are discovered from
+"Package-Requires" headers in source files and from a Cask file.
EOF
}
@@ -137,11 +149,69 @@ function elisp-checkdoc-file {
(when makem-checkdoc-errors-p
(kill-emacs 1))))
+(setq checkdoc-spellcheck-documentation-flag t)
(makem-checkdoc-files-and-exit)
EOF
echo $file
}
+function elisp-check-declare-file {
+ # Since check-declare doesn't have a batch function that exits
+ # non-zero when errors are found, we make one.
+ local file=$(mktemp)
+
+ cat >$file <<EOF
+(require 'check-declare)
+
+(defun makem-check-declare-files-and-exit ()
+ "Run check-declare-files on files remaining on command line, exiting
non-zero if there are warnings."
+ (let* ((files (mapcar #'expand-file-name command-line-args-left))
+ (errors (apply #'check-declare-files files)))
+ (when errors
+ (with-current-buffer check-declare-warning-buffer
+ (print (buffer-string)))
+ (kill-emacs 1))))
+EOF
+ echo $file
+}
+
+function elisp-lint-indent-file {
+ # This function prints warnings for indentation errors and exits
+ # non-zero when errors are found.
+ local file=$(mktemp)
+
+ cat >"$file" <<EOF
+(require 'cl-lib)
+
+(defun makem-lint-indent-batch-and-exit ()
+ "Print warnings for files which are not indented properly, then exit.
+Exits non-zero if mis-indented lines are found. Checks files in
+'command-line-args-left'."
+ (let ((errors-p))
+ (cl-labels ((lint-file (file)
+ (find-file file)
+ (let ((tick (buffer-modified-tick)))
+ (let ((inhibit-message t))
+ (indent-region (point-min) (point-max)))
+ (when (/= tick (buffer-modified-tick))
+ ;; Indentation changed: warn for each line.
+ (dolist (line (undo-lines buffer-undo-list))
+ (message "%s:%s: Indentation mismatch"
(buffer-name) line))
+ (setf errors-p t))))
+ (undo-lines (undo-list)
+ ;; Return list of lines changed in UNDO-LIST.
+ (nreverse (cl-loop for elt in undo-list
+ when (and (consp elt)
+ (numberp (car elt)))
+ collect (line-number-at-pos
(car elt))))))
+ (mapc #'lint-file (mapcar #'expand-file-name command-line-args-left))
+ (when errors-p
+ (kill-emacs 1)))))
+EOF
+
+ echo "$file"
+}
+
function elisp-package-initialize-file {
local file=$(mktemp)
@@ -149,8 +219,8 @@ function elisp-package-initialize-file {
(require 'package)
(setq package-archives (list (cons "gnu" "https://elpa.gnu.org/packages/")
(cons "melpa" "https://melpa.org/packages/")
- (cons "melpa-stable"
"https://stable.melpa.org/packages/")
- (cons "org" "https://orgmode.org/elpa/")))
+ (cons "melpa-stable"
"https://stable.melpa.org/packages/")))
+$elisp_org_package_archive
(package-initialize)
(setq load-prefer-newer t)
EOF
@@ -160,30 +230,39 @@ EOF
# ** Emacs
function run_emacs {
- debug "run_emacs: $emacs_command -Q --batch
--load=$package_initialize_file -L \"$load_path\" $@"
- if [[ $debug_load_path ]]
- then
- debug $($emacs_command -Q --batch \
- --load=$package_initialize_file \
- -L "$load_path" \
- --eval "(message \"LOAD-PATH: %s\" load-path)" \
- 2>&1)
- fi
+ # NOTE: The sandbox args need to come before the package
+ # initialization so Emacs will use the sandbox's packages.
+ local emacs_command=(
+ "${emacs_command[@]}"
+ -Q
+ "${args_sandbox[@]}"
+ -l $package_initialize_file
+ $arg_batch
+ "${args_load_paths[@]}"
+ )
+
+ # Show debug message with load-path from inside Emacs.
+ [[ $debug_load_path ]] \
+ && debug $("${emacs_command[@]}" \
+ --batch \
+ --eval "(message \"LOAD-PATH: %s\" load-path)" \
+ 2>&1)
+
+ # Set output file.
+ output_file=$(mktemp) || die "Unable to make output file."
+ paths_temp+=("$output_file")
- output_file=$(mktemp)
- $emacs_command -Q --batch \
- --load=$package_initialize_file \
- -L "$load_path" \
- "$@" \
- &>$output_file
+ # Run Emacs.
+ debug "run_emacs: ${emacs_command[@]} $@ &>\"$output_file\""
+ "${emacs_command[@]}" "$@" &>"$output_file"
+ # Check exit code and output.
exit=$?
- [[ $exit != 0 ]] && debug "Emacs exited non-zero: $exit"
- if [[ $verbose -gt 1 || $exit != 0 ]]
- then
- cat $output_file
- fi
- rm -f $output_file
+ [[ $exit != 0 ]] \
+ && debug "Emacs exited non-zero: $exit"
+
+ [[ $verbose -gt 1 || $exit != 0 ]] \
+ && cat $output_file
return $exit
}
@@ -191,7 +270,7 @@ function run_emacs {
# ** Compilation
function batch-byte-compile {
- debug "batch-byte-compile: ERROR-ON-WARN:$compile_error_on_warn FILES:$@"
+ debug "batch-byte-compile: ERROR-ON-WARN:$compile_error_on_warn"
[[ $compile_error_on_warn ]] && local error_on_warn=(--eval "(setq
byte-compile-error-on-warn t)")
@@ -203,37 +282,74 @@ function batch-byte-compile {
# ** Files
-function project-elisp-files {
+function dirs-project {
+ # Echo list of directories to be used in load path.
+ files-project-feature | dirnames
+ files-project-test | dirnames
+}
+
+function files-project-elisp {
# Echo list of Elisp files in project.
- git ls-files 2>/dev/null | egrep "\.el$" | exclude-files
+ git ls-files 2>/dev/null \
+ | egrep "\.el$" \
+ | filter-files-exclude-default \
+ | filter-files-exclude-args
}
-function project-source-files {
- # Echo list of Elisp files that are not tests.
- project-elisp-files | egrep -v "$test_files_regexp" | feature-files
+function files-project-feature {
+ # Echo list of Elisp files that are not tests and provide a feature.
+ files-project-elisp \
+ | egrep -v "$test_files_regexp" \
+ | filter-files-feature
}
-function project-test-files {
+function files-project-test {
# Echo list of Elisp test files.
- project-elisp-files | egrep "$test_files_regexp"
+ files-project-elisp | egrep "$test_files_regexp"
}
-function exclude-files {
+function dirnames {
+ # Echo directory names for files on STDIN.
+ while read file
+ do
+ dirname "$file"
+ done
+}
+
+function filter-files-exclude-default {
# Filter out paths (STDIN) which should be excluded by default.
egrep -v "(/\.cask/|-autoloads.el|.dir-locals)"
}
-function feature-files {
+function filter-files-exclude-args {
+ # Filter out paths (STDIN) which are excluded with --exclude.
+ if [[ ${files_exclude[@]} ]]
+ then
+ (
+ # We use a subshell to set IFS temporarily so we can send
+ # the list of files to grep -F. This is ugly but more
+ # correct than replacing spaces with line breaks. Note
+ # that, for some reason, using IFS="\n" or IFS='\n' doesn't
+ # work, and a literal line break seems to be required.
+ IFS="
+"
+ grep -Fv "${files_exclude[*]}"
+ )
+ else
+ cat
+ fi
+}
+
+function filter-files-feature {
# Read paths on STDIN and echo ones that (provide 'a-feature).
while read path
do
- debug "PATH: $path"
egrep "^\\(provide '" "$path" &>/dev/null \
&& echo "$path"
done
}
-function load-files-args {
+function args-load-files {
# For file in $@, echo "--load $file".
for file in "$@"
do
@@ -241,17 +357,17 @@ function load-files-args {
done
}
-function files_args {
- # For file in STDIN, echo "$file".
- while read file
+function args-load-path {
+ # Echo load-path arguments.
+ for path in $(dirs-project | sort -u)
do
- printf -- '%q ' "$file"
+ printf -- '-L %q ' "$path"
done
}
function test-files-p {
- # Return 0 if $project_test_files is non-empty.
- [[ "${project_test_files[@]}" ]]
+ # Return 0 if $files_project_test is non-empty.
+ [[ "${files_project_test[@]}" ]]
}
function buttercup-tests-p {
@@ -259,7 +375,7 @@ function buttercup-tests-p {
test-files-p || die "No tests found."
debug "Checking for Buttercup tests..."
- grep "(require 'buttercup)" "${project_test_files[@]}" &>/dev/null
+ grep "(require 'buttercup)" "${files_project_test[@]}" &>/dev/null
}
function ert-tests-p {
@@ -270,14 +386,14 @@ function ert-tests-p {
# We check for this rather than "(require 'ert)", because ERT may
# already be loaded in Emacs and might not be loaded with
# "require" in a test file.
- grep "(ert-deftest" "${project_test_files[@]}" &>/dev/null
+ grep "(ert-deftest" "${files_project_test[@]}" &>/dev/null
}
function dependencies {
# Echo list of package dependencies.
# Search package headers.
- egrep '^;; Package-Requires: ' $(project-source-files)
$(project-test-files) \
+ egrep '^;; Package-Requires: ' $(files-project-feature)
$(files-project-test) \
| egrep -o '\([^([:space:]][^)]*\)' \
| egrep -o '^[^[:space:])]+' \
| sed -r 's/\(//g' \
@@ -291,12 +407,77 @@ function dependencies {
fi
}
+# ** Sandbox
+
+function sandbox {
+ # Initialize sandbox.
+
+ # *** Sandbox arguments
+
+ # Check or make user-emacs-directory.
+ if [[ $sandbox_dir ]]
+ then
+ # Directory given as argument: ensure it exists.
+ [[ -d $sandbox_dir ]] || die "Directory doesn't exist: $sandbox_dir"
+
+ # Add Emacs version-specific subdirectory, creating if necessary.
+ sandbox_dir="$sandbox_dir/$(emacs-version)"
+ if ! [[ -d $sandbox_dir ]]
+ then
+ mkdir "$sandbox_dir" || die "Unable to make sandbox subdir:
$sandbox_dir"
+ fi
+ else
+ # Not given: make temp directory, and delete it on exit.
+ local sandbox_dir=$(mktemp -d) || die "Unable to make sandbox dir."
+ paths_temp+=("$sandbox_dir")
+ fi
+
+ # Make argument to load init file if it exists.
+ init_file="$sandbox_dir/init.el"
+ [[ -r $init_file ]] \
+ && local args_load_init_file=(--load "$init_file")
+
+ # Set sandbox args. This is a global variable used by the run_emacs
function.
+ args_sandbox=(
+ --eval "(setq user-emacs-directory (file-truename \"$sandbox_dir\"))"
+ --eval "(setq user-init-file (file-truename \"$init_file\"))"
+ "${args_load_init_file[@]}"
+ )
+
+ # Add package-install arguments for dependencies.
+ if [[ $install_deps ]]
+ then
+ local deps=($(dependencies))
+ debug "Installing dependencies: ${deps[@]}"
+
+ for package in "${deps[@]}"
+ do
+ args_sandbox_package_install+=(--eval "(package-install
'$package)")
+ done
+ fi
+
+ # *** Install packages into sandbox
+
+ if [[ ${args_sandbox_package_install[@]} ]]
+ then
+ # Initialize the sandbox (installs packages once rather than for every
rule).
+ debug "Initializing sandbox..."
+
+ run_emacs \
+ --eval "(package-refresh-contents)" \
+ "${args_sandbox_package_install[@]}" \
+ || die "Unable to initialize sandbox."
+ fi
+
+ debug "Sandbox initialized."
+}
+
# ** Utility
function cleanup {
- # Remove temporary paths (${temp_paths[@]}).
+ # Remove temporary paths (${paths_temp[@]}).
- for path in "${temp_paths[@]}"
+ for path in "${paths_temp[@]}"
do
if [[ $debug ]]
then
@@ -310,6 +491,52 @@ function cleanup {
done
}
+function echo-unset-p {
+ # Echo 0 if $1 is set, otherwise 1. IOW, this returns the exit
+ # code of [[ $1 ]] as STDOUT.
+ [[ $1 ]]
+ echo $?
+}
+
+function ensure-package-available {
+ # If package $1 is available, return 0. Otherwise, return 1, and
+ # if $2 is set, give error otherwise verbose. Outputting messages
+ # here avoids repetition in callers.
+ local package=$1
+ local direct_p=$2
+
+ if ! run_emacs --load $package &>/dev/null
+ then
+ if [[ $direct_p ]]
+ then
+ error "$package not available."
+ else
+ verbose 2 "$package not available."
+ fi
+ return 1
+ fi
+}
+
+function ensure-tests-available {
+ # If tests of type $1 (like "ERT") are available, return 0. Otherwise, if
+ # $2 is set, give an error and return 1; otherwise give verbose message.
$1
+ # should have a corresponding predicate command, like ert-tests-p for ERT.
+ local test_name=$1
+ local test_command="${test_name,,}-tests-p" # Converts name to lowercase.
+ local direct_p=$2
+
+ if ! $test_command
+ then
+ if [[ $direct_p ]]
+ then
+ error "$test_name tests not found."
+ else
+ verbose 2 "$test_name tests not found."
+ fi
+ return 1
+ fi
+}
+
function echo_color {
# This allows bold, italic, etc. without needing a function for
# each variation.
@@ -349,9 +576,9 @@ function log {
echo "LOG ($(ts)): $@" >&2
}
function log_color {
- local color=$1
+ local color_name=$1
shift
- echo_color $color "LOG ($(ts)): $@" >&2
+ echo_color $color_name "LOG ($(ts)): $@" >&2
}
function success {
if [[ $verbose -ge 2 ]]
@@ -363,11 +590,11 @@ function verbose {
# $1 is the verbosity level, rest are echoed when appropriate.
if [[ $verbose -ge $1 ]]
then
- [[ $1 -eq 1 ]] && local color=blue
- [[ $1 -ge 2 ]] && local color=cyan
+ [[ $1 -eq 1 ]] && local color_name=blue
+ [[ $1 -ge 2 ]] && local color_name=cyan
shift
- log_color $color "$@" >&2
+ log_color $color_name "$@" >&2
fi
}
@@ -375,9 +602,17 @@ function ts {
date "+%Y-%m-%d %H:%M:%S"
}
+function emacs-version {
+ # Echo Emacs version number.
+ run_emacs --eval "(princ emacs-version)" || die "Unable to get Emacs
version."
+}
+
# * Rules
# These functions are intended to be called as rules, like a Makefile.
+# Some rules test $1 to determine whether the rule is being called
+# directly or from a meta-rule; if directly, an error is given if the
+# rule can't be run, otherwise it's skipped.
function all {
verbose 1 "Running all rules..."
@@ -391,30 +626,51 @@ function compile {
unset compile # Only compile once.
verbose 1 "Compiling..."
- debug "Byte-compile files: ${project_byte_compile_files[@]}"
+ debug "Byte-compile files: ${files_project_byte_compile[@]}"
- batch-byte-compile "${project_byte_compile_files[@]}" \
+ batch-byte-compile "${files_project_byte_compile[@]}" \
&& success "Compiling finished without errors." \
|| error "Compilation failed."
}
+function batch {
+ # Run Emacs with $args_batch and with project source and test files loaded.
+ verbose 1 "Executing Emacs with arguments: ${args_batch[@]}"
+
+ run_emacs \
+ $(args-load-files "${files_project_feature[@]}"
"${files_project_test[@]}") \
+ "${args_batch_interactive[@]}"
+}
+
+function interactive {
+ # Run Emacs interactively. Most useful with --sandbox and --install-deps.
+ unset arg_batch
+ run_emacs \
+ $(args-load-files "${files_project_feature[@]}"
"${files_project_test[@]}") \
+ "${args_batch_interactive[@]}"
+ arg_batch="--batch"
+}
+
function lint {
verbose 1 "Linting..."
lint-checkdoc
lint-compile
+ lint-declare
+ lint-indent
lint-package
+ lint-regexps
}
function lint-checkdoc {
verbose 1 "Linting checkdoc..."
local checkdoc_file="$(elisp-checkdoc-file)"
- temp_paths+=("$checkdoc_file")
+ paths_temp+=("$checkdoc_file")
run_emacs \
--load="$checkdoc_file" \
- "${project_source_files[@]}" \
+ "${files_project_feature[@]}" \
&& success "Linting checkdoc finished without errors." \
|| error "Linting checkdoc failed."
}
@@ -423,23 +679,68 @@ function lint-compile {
verbose 1 "Linting compilation..."
compile_error_on_warn=true
- batch-byte-compile "${project_byte_compile_files[@]}" \
+ batch-byte-compile "${files_project_byte_compile[@]}" \
&& success "Linting compilation finished without errors." \
|| error "Linting compilation failed."
unset compile_error_on_warn
}
+function lint-declare {
+ verbose 1 "Linting declarations..."
+
+ local check_declare_file="$(elisp-check-declare-file)"
+ paths_temp+=("$check_declare_file")
+
+ run_emacs \
+ --load "$check_declare_file" \
+ -f makem-check-declare-files-and-exit \
+ "${files_project_feature[@]}" \
+ && success "Linting declarations finished without errors." \
+ || error "Linting declarations failed."
+}
+
+function lint-indent {
+ verbose 1 "Linting indentation..."
+
+ # We load project source files as well, because they may contain
+ # macros with (declare (indent)) rules which must be loaded to set
+ # indentation.
+
+ run_emacs \
+ --load "$(elisp-lint-indent-file)" \
+ $(args-load-files "${files_project_feature[@]}"
"${files_project_test[@]}") \
+ --funcall makem-lint-indent-batch-and-exit \
+ "${files_project_feature[@]}" "${files_project_test[@]}" \
+ && success "Linting indentation finished without errors." \
+ || error "Linting indentation failed."
+}
+
function lint-package {
+ ensure-package-available package-lint $1 || return $(echo-unset-p $1)
+
verbose 1 "Linting package..."
run_emacs \
--load package-lint \
--funcall package-lint-batch-and-exit \
- "${project_source_files[@]}" \
+ "${files_project_feature[@]}" \
&& success "Linting package finished without errors." \
|| error "Linting package failed."
}
+function lint-regexps {
+ ensure-package-available relint $1 || return $(echo-unset-p $1)
+
+ verbose 1 "Linting regexps..."
+
+ run_emacs \
+ --load relint \
+ --funcall relint-batch \
+ "${files_project_source[@]}" \
+ && success "Linting regexps finished without errors." \
+ || error "Linting regexps failed."
+}
+
function tests {
verbose 1 "Running all tests..."
@@ -447,14 +748,24 @@ function tests {
test-buttercup
}
+function test-ert-interactive {
+ verbose 1 "Running ERT tests interactively..."
+
+ unset arg_batch
+ run_emacs \
+ $(args-load-files "${files_project_test[@]}") \
+ --eval "(ert-run-tests-interactively t)"
+ arg_batch="--batch"
+}
+
function test-buttercup {
- buttercup-tests-p || return 0
+ ensure-tests-available Buttercup $1 || return $(echo-unset-p $1)
compile || die
verbose 1 "Running Buttercup tests..."
local buttercup_file="$(elisp-buttercup-file)"
- temp_paths+=("$buttercup_file")
+ paths_temp+=("$buttercup_file")
run_emacs \
--load buttercup \
@@ -465,14 +776,14 @@ function test-buttercup {
}
function test-ert {
- ert-tests-p || return 0
+ ensure-tests-available ERT $1 || return $(echo-unset-p $1)
compile || die
verbose 1 "Running ERT tests..."
- debug "Test files: ${project_test_files[@]}"
+ debug "Test files: ${files_project_test[@]}"
run_emacs \
- $(load-files-args "${project_test_files[@]}") \
+ $(args-load-files "${files_project_test[@]}") \
-f ert-run-tests-batch-and-exit \
&& success "ERT tests finished without errors." \
|| error "ERT tests failed."
@@ -480,11 +791,13 @@ function test-ert {
# * Defaults
-test_files_regexp='^(tests?|t)/'
-emacs_command="emacs"
+test_files_regexp='^((tests?|t)/)|-test.el$|^test-'
+
+emacs_command=("emacs")
errors=0
verbose=0
compile=true
+arg_batch="--batch"
# MAYBE: Disable color if not outputting to a terminal. (OTOH, the
# colorized output is helpful in CI logs, and I don't know if,
@@ -510,7 +823,6 @@ color=true
# something, which seems like getting too smart for our own good.
# TODO: Emit a warning if .ELC files that don't match any .EL files are
detected.
-load_path="."
# ** Colors
@@ -524,22 +836,28 @@ COLOR_purple='\e[0;35m'
COLOR_cyan='\e[0;36m'
COLOR_white='\e[0;37m'
-# * Project files
+# ** Package system args
-# MAYBE: Option to not byte-compile test files. (OTOH, byte-compiling reveals
many
-# errors that would otherwise go unnoticed, so it's worth it to fix the
warnings.)
-project_source_files=($(project-source-files))
-project_test_files=($(project-test-files))
-project_byte_compile_files=("${project_source_files[@]}"
"${project_test_files[@]}")
+args_package_archives=(
+ --eval "(add-to-list 'package-archives '(\"gnu\" .
\"https://elpa.gnu.org/packages/\") t)"
+ --eval "(add-to-list 'package-archives '(\"melpa\" .
\"https://melpa.org/packages/\") t)"
+)
-package_initialize_file="$(elisp-package-initialize-file)"
-temp_paths+=("$package_initialize_file")
+args_org_package_archives=(
+ --eval "(add-to-list 'package-archives '(\"org\" .
\"https://orgmode.org/elpa/\") t)"
+)
+
+args_package_init=(
+ --eval "(package-initialize)"
+)
+
+elisp_org_package_archive="(add-to-list 'package-archives '(\"org\" .
\"https://orgmode.org/elpa/\") t)"
# * Args
args=$(getopt -n "$0" \
- -o dhi:sS:vf:C \
- -l
auto-install,debug,debug-load-path,help,install:,verbose,file:,no-color,no-compile,sandbox,sandbox-dir:
\
+ -o dhe:E:i:sS:vf:CO \
+ -l
exclude:,emacs:,install-deps,install-linters,debug,debug-load-path,help,install:,verbose,file:,no-color,no-compile,no-org-repo,sandbox,sandbox-dir:
\
-- "$@") \
|| { usage; exit 1; }
eval set -- "$args"
@@ -547,8 +865,12 @@ eval set -- "$args"
while true
do
case "$1" in
- --auto-install)
- auto_install=true
+ --install-deps)
+ install_deps=true
+ ;;
+ --install-linters)
+ args_sandbox_package_install+=(--eval "(package-install
'package-lint)"
+ --eval "(package-install 'relint)")
;;
-d|--debug)
debug=true
@@ -561,9 +883,13 @@ do
usage
exit
;;
+ -E|--emacs)
+ shift
+ emacs_command=($1)
+ ;;
-i|--install)
shift
- sandbox_install_packages_args+=(--install "$1")
+ args_sandbox_package_install+=(--eval "(package-install '$1)")
;;
-s|--sandbox)
sandbox=true
@@ -576,11 +902,19 @@ do
-v|--verbose)
((verbose++))
;;
+ -e|--exclude)
+ shift
+ debug "Excluding file: $1"
+ files_exclude+=("$1")
+ ;;
-f|--file)
shift
project_source_files+=("$1")
project_byte_compile_files+=("$1")
;;
+ -O|--no-org-repo)
+ unset elisp_org_package_archive
+ ;;
--no-color)
unset color
;;
@@ -601,67 +935,59 @@ done
debug "ARGS: $args"
debug "Remaining args: ${rest[@]}"
+# Set package elisp (which depends on --no-org-repo arg).
+package_initialize_file="$(elisp-package-initialize-file)"
+paths_temp+=("$package_initialize_file")
+
# * Main
trap cleanup EXIT INT TERM
-if ! [[ ${project_source_files[@]} ]]
+# Discover project files.
+files_project_feature=($(files-project-feature))
+files_project_test=($(files-project-test))
+files_project_byte_compile=("${files_project_feature[@]}"
"${files_project_test[@]}")
+
+debug "EXCLUDING FILES: ${files_exclude[@]}"
+debug "FEATURE FILES: ${files_project_feature[@]}"
+debug "TEST FILES: ${files_project_test[@]}"
+debug "BYTE-COMPILE FILES: ${files_project_byte_compile[@]}"
+
+if ! [[ ${files_project_feature[@]} ]]
then
error "No files specified and not in a git repo."
exit 1
fi
-if [[ $sandbox ]]
-then
- # Setup sandbox.
- type emacs-sandbox.sh &>/dev/null || die "emacs-sandbox.sh not found."
-
- if ! [[ $sandbox_dir ]]
- then
- # No sandbox dir specified: make temp dir and remove it on exit.
- sandbox_dir=$(mktemp -d) || die "Unable to make temp dir."
- temp_paths+=("$sandbox_dir")
- fi
+# Set load path.
+args_load_paths=($(args-load-path))
+debug "LOAD PATH ARGS: ${args_load_paths[@]}"
- sandbox_basic_args=(
- -d "$sandbox_dir"
- )
- [[ $debug ]] && sandbox_basic_args+=(--debug)
+# Initialize sandbox.
+[[ $sandbox ]] && sandbox
- if [[ $auto_install ]]
+# Run rules.
+for rule in "${rest[@]}"
+do
+ if [[ $batch || $interactive ]]
then
- # Add dependencies to package install list.
- deps=($(dependencies))
- debug "Installing dependencies: ${deps[@]}"
-
- for package in "${deps[@]}"
- do
- sandbox_install_packages_args+=(--install $package)
- done
- fi
+ debug "Adding batch/interactive argument: $rule"
+ args_batch_interactive+=("$rule")
- if [[ ${sandbox_install_packages_args[@]} ]]
+ elif [[ $rule = batch ]]
then
- # Initialize the sandbox (installs packages once rather than for every
rule).
- emacs_command="emacs-sandbox.sh ${sandbox_basic_args[@]}
${sandbox_install_packages_args[@]} -- "
- debug "Initializing sandbox..."
-
- run_emacs || die "Unable to initialize sandbox."
- fi
-
- # After the sandbox is initialized and packages are installed, set the
command
- # to prevent the package lists from being refreshed on each invocation.
- emacs_command="emacs-sandbox.sh ${sandbox_basic_args[@]}
--no-refresh-packages -- "
-
- debug "Sandbox initialized."
-fi
+ # Remaining arguments are passed to Emacs.
+ batch=true
+ elif [[ $rule = interactive ]]
+ then
+ # Remaining arguments are passed to Emacs.
+ interactive=true
-# Run rules.
-for rule in "${rest[@]}"
-do
- if type "$rule" 2>/dev/null | grep "$rule is a function" &>/dev/null
+ elif type -t "$rule" 2>/dev/null | grep function &>/dev/null
then
- $rule
+ # Pass called-directly as $1 to indicate that the rule is
+ # being called directly rather than from a meta-rule.
+ $rule called-directly
elif [[ $rule = test ]]
then
# Allow the "tests" rule to be called as "test". Since "test"
@@ -672,6 +998,10 @@ do
fi
done
+# Batch/interactive rules.
+[[ $batch ]] && batch
+[[ $interactive ]] && interactive
+
if [[ $errors -gt 0 ]]
then
log_color red "Finished with $errors errors."
- [elpa] externals/plz e14ea7327d 14/81: Tidying, (continued)
- [elpa] externals/plz e14ea7327d 14/81: Tidying, ELPA Syncer, 2022/05/11
- [elpa] externals/plz 2b7944e0f9 05/81: Changes, ELPA Syncer, 2022/05/11
- [elpa] externals/plz 950a5498cb 16/81: Tidy, ELPA Syncer, 2022/05/11
- [elpa] externals/plz 44e6f02064 17/81: Binary content, ELPA Syncer, 2022/05/11
- [elpa] externals/plz 5bd683ead8 19/81: Tidy tests, ELPA Syncer, 2022/05/11
- [elpa] externals/plz 3249835c8b 18/81: Tidy tests, ELPA Syncer, 2022/05/11
- [elpa] externals/plz 21a7318f1c 26/81: Tests: Tidy/rename, ELPA Syncer, 2022/05/11
- [elpa] externals/plz 3dd2598fe9 24/81: Tidy, ELPA Syncer, 2022/05/11
- [elpa] externals/plz 3cc6747035 28/81: Meta: Add comm keyword, ELPA Syncer, 2022/05/11
- [elpa] externals/plz 51404566fa 29/81: Notes: Add fetch.el, ELPA Syncer, 2022/05/11
- [elpa] externals/plz b77283748b 31/81: Meta: Update makem.sh,
ELPA Syncer <=
- [elpa] externals/plz 56c66c4421 32/81: Add/Change: :as 'binary, ELPA Syncer, 2022/05/11
- [elpa] externals/plz 1bb701f1c1 36/81: Change/Fix: Downcase and intern header keys, ELPA Syncer, 2022/05/11
- [elpa] externals/plz 6f8dfb83de 34/81: Tests: (plz-test-get-response) Change to macro, ELPA Syncer, 2022/05/11
- [elpa] externals/plz baf93bb80a 39/81: Fix: (plz--curl) Header args, ELPA Syncer, 2022/05/11
- [elpa] externals/plz 33438b7105 35/81: CI: Enable testing of all branches, ELPA Syncer, 2022/05/11
- [elpa] externals/plz 439fb383d9 37/81: Notes: Add idea about finalizers, ELPA Syncer, 2022/05/11
- [elpa] externals/plz 65dbc0f219 41/81: Change/Fix: (plz--sentinel) Use exhaustive pcase, ELPA Syncer, 2022/05/11
- [elpa] externals/plz 7eff40f276 44/81: Add: plz-finally, ELPA Syncer, 2022/05/11
- [elpa] externals/plz 27010c20e1 45/81: Meta: Update makem.sh, etc., ELPA Syncer, 2022/05/11
- [elpa] externals/plz f34efa052c 48/81: Fix: set-buffer-multibyte nil for binary, ELPA Syncer, 2022/05/11