Skip to content

Commit 192638f

Browse files
committed
add top-level error recovery hook
elpaca-error-functions: hook run when elpaca errors are signaled. The first function to return non-nil suppresses the error. elpaca<-create: decompose struct creation so elpaca-error-functions has a struct to work with for most errors. Run elpaca-error-functions when an elpaca-error is signaled. elpaca (macro): catch elpaca-abort signal elpaca (struct): add declaration field for declared order
1 parent cf50acf commit 192638f

File tree

3 files changed

+35
-22
lines changed

3 files changed

+35
-22
lines changed

elpaca-git.el

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ Type is `local' for a local filesystem path, `remote' for a remote URL, or nil."
6767
(user nil)
6868
(info (concat url (or remote repo) hostname))
6969
(key (or (and info (> (length info) 0) (intern info))
70-
(error "Cannot determine URL from recipe: %S" recipe)))
70+
(signal 'elpaca-url-error recipe)))
7171
(mono-repo (elpaca-alist-get key elpaca--source-dirs))
7272
(dirs (and (not mono-repo) (mapcar #'cdr elpaca--source-dirs)))
7373
(name (cond
@@ -104,7 +104,7 @@ Type is `local' for a local filesystem path, `remote' for a remote URL, or nil."
104104
(repo url) &allow-other-keys)
105105
recipe
106106
(when (consp repo) (setq repo (car repo))) ; Handle :repo rename
107-
(pcase (elpaca-git--repo-type (or repo (error "Unable to determine recipe URL")))
107+
(pcase (elpaca-git--repo-type (or repo (signal 'elpaca-url-error recipe)))
108108
('remote repo)
109109
('local (expand-file-name repo))
110110
(_ (let ((p (pcase protocol
@@ -348,8 +348,9 @@ COMMAND must satisfy `elpaca--make-process' :command SPEC arg, which see."
348348

349349
(cl-defmethod elpaca-source-dir ((e (elpaca git)))
350350
"Return source directory for :type `git` E."
351-
(or (elpaca-git-repo-dir (elpaca<-recipe e))
352-
(error "Unable to determine source dir for %S" (elpaca<-id e))))
351+
(condition-case err
352+
(elpaca-git-repo-dir (elpaca<-recipe e))
353+
(elpaca-error (signal (car err) (cdr err)))))
353354

354355
(cl-defmethod elpaca-ref ((e (elpaca git)))
355356
"Return :ref for :type git E."

elpaca-tar.el

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@
5757
(setq template (replace-regexp-in-string
5858
(symbol-name key) (format "%s" val) template nil t))
5959
finally return template))
60-
(error "Unable to determine URL from recipe %s" recipe)))
60+
(signal 'elpaca-url-error recipe)))
6161

6262
(defvar url-http-response-status)
6363
(defvar url-http-end-of-headers)

elpaca.el

Lines changed: 29 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -407,7 +407,7 @@ When INTERACTIVE is non-nil, `yank' the recipe to the clipboard."
407407
(cl-defstruct (elpaca (:constructor elpaca<--create) (:type list) (:named)
408408
(:conc-name elpaca<-))
409409
"Order for queued processing."
410-
id package props order statuses
410+
id package declaration order statuses
411411
build-dir source-dir main
412412
files build-steps recipe blocking blockers
413413
dependencies dependents
@@ -582,21 +582,27 @@ The first function, if any, which returns non-nil is used." :type 'hook)
582582
"Return E's source directory."
583583
(expand-file-name (elpaca<-package e) elpaca-sources-directory))
584584

585-
(defun elpaca<-create (order)
586-
"Create a new elpaca struct from ORDER."
587-
(let* ((id (elpaca--first order))
588-
(recipe (elpaca-recipe order))
589-
(build-dir (elpaca-build-dir recipe))
590-
(e (elpaca<--create
591-
:id id :package (symbol-name id)
592-
:order order :build-dir build-dir
593-
:recipe recipe :builtp (and build-dir (file-exists-p build-dir)))))
594-
(when-let* ((recipe)
595-
(registered (elpaca-alist-get (plist-get recipe :type) elpaca-types)))
596-
(require registered)) ;;@TODO: optimize lookup by tracking separate from `features'?
597-
(setf (elpaca<-source-dir e) (elpaca-source-dir e)
598-
(elpaca<-build-steps e) (elpaca-build-steps e))
599-
e))
585+
(defun elpaca<-create (declaration)
586+
"Create a new elpaca struct from DECLARATION."
587+
(let* ((id (elpaca--first declaration))
588+
(e (elpaca<--create :id id :package (symbol-name id) :declaration declaration)))
589+
(condition-case err
590+
(progn
591+
(setf (elpaca<-order e) (elpaca--normalize-order declaration)
592+
(elpaca<-recipe e) (elpaca--normalize-recipe (elpaca<-order e))
593+
(elpaca<-build-dir e) (elpaca-build-dir (elpaca<-recipe e))
594+
(elpaca<-builtp e) (when-let* ((build-dir (elpaca<-build-dir e)))
595+
(file-exists-p build-dir)))
596+
(when-let* ((recipe (elpaca<-recipe e))
597+
(registered (elpaca-alist-get (plist-get recipe :type) elpaca-types)))
598+
(require registered)) ;;@TODO: optimize lookup by tracking separate from `features'?
599+
(setf (elpaca<-source-dir e) (elpaca-source-dir e)
600+
(elpaca<-build-steps e) (elpaca-build-steps e))
601+
e)
602+
(elpaca-error
603+
(if (run-hook-with-args-until-success 'elpaca-error-functions e err)
604+
(throw 'elpaca-abort nil)
605+
(signal (car err) (cdr err)))))))
600606

601607
(declare-function elpaca-ui--update-search-query "elpaca-ui")
602608
(defun elpaca--update-log-buffer ()
@@ -1466,13 +1472,19 @@ When quit with \\[keyboard-quit], running sub-processes are not stopped."
14661472
(setq elpaca--interactive-timer
14671473
(run-at-time elpaca-interactive-interval nil #'elpaca-process-queues))))))
14681474

1475+
(defcustom elpaca-error-functions nil
1476+
"Abnormal hook to catch top-level `elpaca-error' signals.
1477+
Each element is a function accepting an E struct and error object.
1478+
The first to return non-nil suppresses the error."
1479+
:type 'hook)
1480+
14691481
;;;###autoload
14701482
(defmacro elpaca (order &rest body)
14711483
"Queue ORDER for asynchronous installation/activation.
14721484
Evaluate BODY forms synchronously once ORDER's queue is processed.
14731485
See Info node `(elpaca) Basic Concepts'."
14741486
(declare (indent 1) (debug form))
1475-
`(elpaca--expand-declaration ',order ',body))
1487+
`(catch 'elpaca-abort (elpaca--expand-declaration ',order ',body)))
14761488

14771489
(defvar elpaca--try-package-history nil "History for `elpaca-try'.")
14781490
;;;###autoload

0 commit comments

Comments
 (0)