#! /bin/sh # Eldev --- Elisp development tool. # # Copyright (C) 2019-2024 Paul Pogonyshev # # Author: Paul Pogonyshev # Homepage: https://github.com/emacs-eldev/eldev set -e if [ -z "$ELDEV_EMACS" ]; then if [ -z "$EMACS" ]; then ELDEV_EMACS=emacs else ELDEV_EMACS=$EMACS fi fi ELDEV_CMD=$0 # For determining whether to enable coloring in automatic mode; Elisp has no `isatty' and # it doesn't look like we could use `terminal-parameters' etc. in batch mode. Also could # try determining background color with "\e]11;?\a", but that doesn't work in a subshell # and cutting it out of our own output in compatible manner is a nightmare. ELDEV_TTY= if test -t 1; then ELDEV_TTY=t fi export ELDEV_EMACS export ELDEV_CMD export ELDEV_TTY $ELDEV_EMACS --batch --no-site-file --no-site-lisp \ --execute '(let ((eldev--emacs-version (format "%s.%s" emacs-major-version emacs-minor-version)) (eldev--dir (getenv "ELDEV_DIR")) ;; This is intentional. First, this is in case ELDEV_LOCAL is ;; defined, second, this is just Eldev default for packages. (load-prefer-newer t)) ;; Setting `debug-on-error'\'' would be useful, but it can break many ;; `package-*'\'' functions, since those use `with-demoted-errors'\'' and ;; so `condition-case-unless-debug'\''. (unless (and (fboundp '\''version<=) (version<= "24.1" eldev--emacs-version)) (error "Eldev requires Emacs 24.1 or newer")) (setf package-user-dir (expand-file-name "bootstrap" (expand-file-name eldev--emacs-version (if (> (length eldev--dir) 0) eldev--dir (if (file-directory-p "~/.eldev") "~/.eldev" ;; Duplicating not-yet-available code from `eldev-xdg-cache-home'\''. (expand-file-name "eldev" (let ((eldev--xdg-cache-dir (getenv "XDG_CACHE_HOME"))) (if (and eldev--xdg-cache-dir (file-name-absolute-p eldev--xdg-cache-dir)) eldev--xdg-cache-dir "~/.cache"))))))) package-directory-list nil package-archives nil) (require '\''package) (package-initialize t) (let ((package-archives '\''(("melpa-stable" . "http://stable.melpa.org/packages/"))) (archive-name "MELPA Stable") (inhibit-message t) (eldev-local (getenv "ELDEV_LOCAL")) eldev-pkg requirements) (unless (= (length eldev-local) 0) (if (string-prefix-p ":pa:" eldev-local) (setf package-archives `(("bootstrap-pa" . ,(file-name-as-directory (substring eldev-local (length ":pa:"))))) archive-name "a local package archive") (with-temp-buffer (insert-file-contents (expand-file-name "eldev.el" eldev-local)) (setf eldev-pkg (package-buffer-info) (package-desc-dir eldev-pkg) (expand-file-name eldev-local)) ;; Currently Eldev has no external dependencies, but let'\''s be generic. (dolist (requirement (package-desc-reqs eldev-pkg)) (unless (package-activate (car requirement)) (push requirement requirements)))))) (when (if eldev-pkg requirements (not (package-activate '\''eldev))) (let ((inhibit-message nil)) (message "Bootstrapping Eldev for Emacs %s from %s...\n" eldev--emacs-version archive-name) (when eldev-pkg (message "Eldev package itself will be used from `%s'\''\n" eldev-local))) ;; See `eldev-retrying-for-robustness'\''; since Eldev is not bootstrapped yet, we have ;; to inline everything. No control from command line here. (let* ((all-retry-delays (when (equal (getenv "CI") "true") '\''(30 60 120 180 300))) (remaining-delays all-retry-delays)) (catch '\''obtained-result (while t (condition-case error (throw '\''obtained-result (let ((debug-on-error (and debug-on-error (null remaining-delays)))) ;; See similar workarounds for `package-refresh-contents'\'' in `eldev.el'\''. (let* (failure (failure-catcher (lambda (original archive &rest arguments) (unless failure (condition-case-unless-debug error (apply original archive arguments) (error (setf failure (cons error (if (consp archive) (car archive) archive))))))))) (advice-add '\''package--download-one-archive :around failure-catcher) (unwind-protect (package-refresh-contents) (advice-remove '\''package--download-one-archive failure-catcher)) (when failure (error "%s (when updating contents of package archive `%s'\'')" (error-message-string (car failure)) (cdr failure)))))) (error (let ((inhibit-message nil) (delay (pop remaining-delays))) (unless delay (when all-retry-delays (message "Giving up: too many retries already")) (signal (car error) (cdr error))) (message "%s" (error-message-string error)) (message "Assuming this is an intermittent problem, waiting %s before retrying...\n" (if (< delay 60) (format "%s s" delay) (format "%s m" (/ delay 60)))) (sleep-for delay) (let ((n (- 5 (length remaining-delays)))) (message "Retry #%d%s..." n (if (= n 5) ", the last" " of maximum 5"))))))))) (if eldev-pkg (package-download-transaction (package-compute-transaction nil requirements)) (package-install '\''eldev))) (when eldev-pkg (push `(eldev . (,eldev-pkg)) package-alist) ;; `package--autoloads-file-name'\'' is package-private. (let* ((autoloads-file (expand-file-name (format "%s-autoloads" (package-desc-name eldev-pkg)) (package-desc-dir eldev-pkg))) (autoloads-disabler (lambda (do-load file &rest args) (unless (equal file autoloads-file) (apply do-load file args))))) ;; Otherwise old Emacs versions print an ugly error having not found the autoloads file. (advice-add #'\''load :around autoloads-disabler) (package-activate-1 eldev-pkg) ;; As of commit 1d5b164109b in Emacs repository, `package-activate-1'\'' no longer modifies `load-path'\'', ;; leaving this to the autoloads file. As we don'\''t have such a file, we have to do that ourselves. (add-to-list '\''load-path (package-desc-dir eldev-pkg)) (advice-remove #'\''load autoloads-disabler)))) (require '\''eldev) (eldev-start-up))' \ --execute "(kill-emacs (eldev-cli (append (cdr (member \"--\" command-line-args)) nil)))" \ -- "$@"