[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals-release/plz df44acec4b 6/6: Merge: v0.9
From: |
ELPA Syncer |
Subject: |
[elpa] externals-release/plz df44acec4b 6/6: Merge: v0.9 |
Date: |
Mon, 10 Jun 2024 15:59:32 -0400 (EDT) |
branch: externals-release/plz
commit df44acec4baf9ae1f2d56ff1e40fada32681a097
Merge: 9b681d4893 399ad3e1aa
Author: Adam Porter <adam@alphapapa.net>
Commit: Adam Porter <adam@alphapapa.net>
Merge: v0.9
---
.github/workflows/test.yml | 9 +-
README.org | 27 +++-
plz.el | 336 ++++++++++++++++++++++++++++++---------------
3 files changed, 250 insertions(+), 122 deletions(-)
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 0f991e4057..0aa11841e5 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -41,16 +41,13 @@ jobs:
fail-fast: false
matrix:
emacs_version:
- # FIXME: The 26.3 test fails to initialize with the error
- # "Package ‘emacs-27.1’ is unavailable", which happens just
- # after "Package refresh done". Not sure what the cause is.
- # But I don't want the whole suite marked as failing because
- # of 26.3 right now, so commenting it out.
- # - 26.3
- 27.1
- 27.2
- 28.1
- 28.2
+ - 29.1
+ - 29.2
+ - 29.3
- snapshot
steps:
- uses: purcell/setup-emacs@master
diff --git a/README.org b/README.org
index d3d27d948c..bc7b2866a6 100644
--- a/README.org
+++ b/README.org
@@ -188,6 +188,27 @@ You may also clear a queue with ~plz-clear~, which cancels
any active or queued
:TOC: :depth 0
:END:
+** 0.9
+
+*Compatibility*
+
++ The minimum supported Emacs version is now 27.1. (It is no longer practical
to test ~plz~ with Emacs versions older than 27.1. For Emacs 26.3, an earlier
version of ~plz~ may be used, or this version might be compatible, with or
without minor changes, which the maintainer cannot offer support for.)
+
+*Changes*
+
++ Option ~plz-timeout~ is removed. (It was the default value for ~plz~'s
~:timeout~ argument, which is passed to Curl as its ~--max-time~ argument,
limiting the total duration of a request operation. This argument should be
unset by default, because larger or slower downloads might not finish within a
certain duration, and it is surprising to the user to have this option set by
default, potentially causing requests to timeout unnecessarily.)
++ Using arguments ~:as 'file~ or ~:as '(file FILENAME)~ now passes the
filename to Curl, allowing it to write the data to the file itself (rather than
receiving the data into an Emacs buffer and then writing it to a file. This
improves performance when downloading large files, significantly reducing
Emacs's CPU and memory usage).
+
+*Fixes*
+
++ Improve workaround for Emacs's process sentinel-related issues. (Don't try
to process response a second time if Emacs calls the sentinel after ~plz~ has
returned for a synchronous request. See
[[https://github.com/alphapapa/plz.el/issues/53][#53]]. Thanks to
[[https://github.com/josephmturner][Joseph Turner]] for extensive help
debugging, and to [[https://ushin.org/][USHIN]] for sponsoring some of this
work.)
++ Inhibit buffer hooks when calling ~generate-new-buffer~ (as extra protection
against "kill buffer?" prompts in case of errors). (See
[[https://github.com/alphapapa/plz.el/pull/52][#52]]. Thanks to
[[https://github.com/mkcms][Michał Krzywkowski]].)
+ - Avoid "kill buffer?" prompts in case of errors on Emacs versions before
28. (See [[https://github.com/alphapapa/plz.el/pull/52][#52]] and
[[https://github.com/alphapapa/plz.el/issues/57][#57]]. Thanks to
[[https://github.com/mkcms][Michał Krzywkowski]].)
+
+*Development*
+
++ ~plz~ is now automatically tested against Emacs versions 27.1, 27.2, 28.1,
28.2, 29.1, 29.2, 29.3, and a recent snapshot of the ~master~ branch (adding
29.2 and 29.3).
+
** 0.8
*Additions*
@@ -265,13 +286,13 @@ You may also clear a queue with ~plz-clear~, which
cancels any active or queued
** 0.4
*Additions*
-+ Support for HTTP ~HEAD~ requests. (Thanks to [[https://ushin.org/][USHIN,
Inc.]] for sponsoring.)
++ Support for HTTP ~HEAD~ requests. (Thanks to [[https://ushin.org/][USHIN]]
for sponsoring.)
*Changes*
-+ Allow sending ~POST~ and ~PUT~ requests without bodies.
([[https://github.com/alphapapa/plz.el/issues/16][#16]]. Thanks to
[[https://github.com/josephmturner][Joseph Turner]] for reporting. Thanks to
[[https://ushin.org/][USHIN, Inc.]] for sponsoring.)
++ Allow sending ~POST~ and ~PUT~ requests without bodies.
([[https://github.com/alphapapa/plz.el/issues/16][#16]]. Thanks to
[[https://github.com/josephmturner][Joseph Turner]] for reporting. Thanks to
[[https://ushin.org/][USHIN]] for sponsoring.)
*Fixes*
-+ All 2xx HTTP status codes are considered successful.
([[https://github.com/alphapapa/plz.el/issues/17][#17]]. Thanks to
[[https://github.com/josephmturner][Joseph Turner]] for reporting. Thanks to
[[https://ushin.org/][USHIN, Inc.]] for sponsoring.)
++ All 2xx HTTP status codes are considered successful.
([[https://github.com/alphapapa/plz.el/issues/17][#17]]. Thanks to
[[https://github.com/josephmturner][Joseph Turner]] for reporting. Thanks to
[[https://ushin.org/][USHIN]] for sponsoring.)
+ Errors are signaled with error data correctly.
*Internal*
diff --git a/plz.el b/plz.el
index 57e247f815..49b37add06 100644
--- a/plz.el
+++ b/plz.el
@@ -5,8 +5,8 @@
;; Author: Adam Porter <adam@alphapapa.net>
;; Maintainer: Adam Porter <adam@alphapapa.net>
;; URL: https://github.com/alphapapa/plz.el
-;; Version: 0.8
-;; Package-Requires: ((emacs "26.3"))
+;; Version: 0.9
+;; Package-Requires: ((emacs "27.1"))
;; Keywords: comm, network, http
;; This file is part of GNU Emacs.
@@ -46,13 +46,14 @@
;;;; Usage:
-;; FIXME(v0.8): Remove the following note.
+;; FIXME(v0.10): Remove the following note.
-;; NOTE: In v0.8 of plz, only one error will be signaled: `plz-error'.
-;; The existing errors, `plz-curl-error' and `plz-http-error', inherit
-;; from `plz-error' to allow applications to update their code while
-;; using v0.7 (i.e. any `condition-case' forms should now handle only
-;; `plz-error', not the other two).
+;; NOTE: In a future version of plz, only one error will be signaled:
+;; `plz-error'. The existing errors, `plz-curl-error' and
+;; `plz-http-error', inherit from `plz-error' to allow applications to
+;; update their code while using earlier versions (i.e. any
+;; `condition-case' forms should now handle only `plz-error', not the
+;; other two).
;; Call function `plz' to make an HTTP request. Its docstring
;; explains its arguments. `plz' also supports other HTTP methods,
@@ -98,6 +99,7 @@
;;;; Requirements
(require 'cl-lib)
+(require 'map)
(require 'rx)
(require 'subr-x)
@@ -243,21 +245,88 @@ This limits how long the connection phase may last (the
\"--connect-timeout\" argument to curl)."
:type 'number)
-(defcustom plz-timeout 60
- "Default request timeout in seconds.
-This limits how long an entire request may take, including the
-connection phase and waiting to receive the response (the
-\"--max-time\" argument to curl)."
- :type 'number)
+;;;; Macros
+
+(require 'warnings)
+
+(cl-defmacro plz-debug (&rest args)
+ ;; Copied from `ement-debug' in Ement.el, which see.
+ "Display a debug warning showing the run-time value of ARGS.
+The warning automatically includes the name of the containing
+function, and it is only displayed if `warning-minimum-log-level'
+is `:debug' at expansion time (otherwise the macro expands to a
+call to `ignore' with ARGS and is eliminated by the
+byte-compiler). When debugging, the form also returns nil so,
+e.g. it may be used in a conditional in place of nil.
+
+Each of ARGS may be a string, which is displayed as-is, or a
+symbol, the value of which is displayed prefixed by its name, or
+a Lisp form, which is displayed prefixed by its first symbol.
+
+Before the actual ARGS arguments, you can write keyword
+arguments, i.e. alternating keywords and values. The following
+keywords are supported:
+
+ :buffer BUFFER Name of buffer to pass to `display-warning'.
+ :level LEVEL Level passed to `display-warning', which see.
+ Default is :debug."
+ ;; TODO: Can we use a compiler macro to handle this more elegantly?
+ (pcase-let* ((fn-name (when byte-compile-current-buffer
+ (with-current-buffer byte-compile-current-buffer
+ ;; This is a hack, but a nifty one.
+ (save-excursion
+ (beginning-of-defun)
+ (cl-second (read (current-buffer)))))))
+ (plist-args (cl-loop while (keywordp (car args))
+ collect (pop args)
+ collect (pop args)))
+ ((map (:buffer buffer) (:level level)) plist-args)
+ (level (or level :debug))
+ (string (cl-loop for arg in args
+ concat (pcase arg
+ ((pred stringp) "%S ")
+ ((pred symbolp)
+ (concat (upcase (symbol-name arg))
":%S "))
+ ((pred listp)
+ (concat "(" (upcase (symbol-name
(car arg)))
+ (pcase (length arg)
+ (1 ")")
+ (_ "...)"))
+ ":%S "))))))
+ (if (eq :debug warning-minimum-log-level)
+ `(let ((fn-name ,(if fn-name
+ `',fn-name
+ ;; In an interpreted function: use
`backtrace-frame' to get the
+ ;; function name (we have to use a little hackery
to figure out
+ ;; how far up the frame to look, but this seems to
work).
+ `(cl-loop for frame in (backtrace-frames)
+ for fn = (cl-second frame)
+ when (not (or (subrp fn)
+ (special-form-p fn)
+ (eq 'backtrace-frames fn)))
+ return (make-symbol (format "%s
[interpreted]" fn))))))
+ (display-warning fn-name (format ,string ,@args) ,level ,buffer)
+ nil)
+ `(ignore ,@args))))
+
+;;;; Compatibility
+
+(defalias 'plz--generate-new-buffer
+ (if (version< emacs-version "28.1")
+ (lambda (name &optional _inhibit-buffer-hooks)
+ "Call `generate-new-buffer' with NAME.
+Compatibility function for Emacs versions <28.1."
+ (generate-new-buffer name))
+ #'generate-new-buffer))
;;;; Functions
;;;;; Public
-(cl-defun plz (method url &rest rest &key headers body else filter finally
noquery
+(cl-defun plz (method url &rest rest &key headers body else filter finally
noquery timeout
(as 'string) (then 'sync)
(body-type 'text) (decode t decode-s)
- (connect-timeout plz-connect-timeout) (timeout
plz-timeout))
+ (connect-timeout plz-connect-timeout))
"Request METHOD from URL with curl.
Return the curl process object or, for a synchronous request, the
selected result.
@@ -314,19 +383,20 @@ structure. If ELSE is nil, a `plz-curl-error' or
`plz-error' structure as the error data. For synchronous
requests, this argument is ignored.
-NOTE: In v0.8 of `plz', only one error will be signaled:
-`plz-error'. The existing errors, `plz-curl-error' and
+NOTE: In a future version of `plz', only one error will be
+signaled: `plz-error'. The existing errors, `plz-curl-error' and
`plz-http-error', inherit from `plz-error' to allow applications
-to update their code while using v0.7 (i.e. any `condition-case'
-forms should now handle only `plz-error', not the other two).
+to update their code while using earlier versions (i.e. any
+`condition-case' forms should now handle only `plz-error', not
+the other two).
FINALLY is an optional function called without argument after
THEN or ELSE, as appropriate. For synchronous requests, this
argument is ignored.
CONNECT-TIMEOUT and TIMEOUT are a number of seconds that limit
-how long it takes to connect to a host and to receive a response
-from a host, respectively.
+how long it takes to connect to a host and to receive a complete
+response from a host, respectively.
NOQUERY is passed to `make-process', which see.
@@ -340,8 +410,8 @@ FILTER function should at least insert output up to the
HTTP body
into the process buffer.
\(To silence checkdoc, we mention the internal argument REST.)"
- ;; FIXME(v0.8): Remove the note about error changes from the docstring.
- ;; FIXME(v0.8): Update error signals in docstring.
+ ;; FIXME(v0.10): Remove the note about error changes from the docstring.
+ ;; FIXME(v0.10): Update error signals in docstring.
(declare (indent defun))
(setf decode (if (and decode-s (not decode))
nil decode))
@@ -351,7 +421,8 @@ into the process buffer.
;; the empty string. See <https://gms.tf/when-curl-sends-100-continue.html>.
;; TODO: Handle "100 Continue" responses and remove this workaround.
(push (cons "Expect" "") headers)
- (let* ((data-arg (pcase-exhaustive body-type
+ (let* (filename
+ (data-arg (pcase-exhaustive body-type
('binary "--data-binary")
('text "--data")))
(curl-command-line-args (append plz-curl-default-args
@@ -375,21 +446,49 @@ into the process buffer.
;; method.
(pcase method
('get
- (list (cons "--dump-header" "-")))
+ (append (list (cons "--dump-header" "-"))
+ (pcase as
+ ('file
+ (setf filename
(make-temp-file "plz-"))
+ (list (cons "--output"
filename)))
+ (`(file ,(and (pred stringp)
as-filename))
+ (when (file-exists-p
as-filename)
+ (error "File exists, will
not overwrite: %S" as-filename))
+ (setf filename as-filename)
+ (list (cons "--output"
filename))))))
((or 'put 'post)
- (list (cons "--dump-header" "-")
- (cons "--request" (upcase
(symbol-name method)))
- ;; It appears that this must be
the last argument
- ;; in order to pass data on the
rest of STDIN.
- (pcase body
- (`(file ,filename)
- ;; Use `expand-file-name'
because curl doesn't
- ;; expand, e.g. "~" into
"/home/...".
- (cons "--upload-file"
(expand-file-name filename)))
- (_ (cons data-arg "@-")))))
+ (append (list (cons "--dump-header" "-")
+ (cons "--request" (upcase
(symbol-name method))))
+ (pcase as
+ ('file
+ (setf filename
(make-temp-file "plz-"))
+ (list (cons "--output"
filename)))
+ (`(file ,(and (pred stringp)
as-filename))
+ (when (file-exists-p
as-filename)
+ (error "File exists, will
not overwrite: %S" as-filename))
+ (setf filename as-filename)
+ (list (cons "--output"
filename))))
+ (list
+ ;; It appears that this must be
the last argument
+ ;; in order to pass data on the
rest of STDIN.
+ (pcase body
+ (`(file ,filename)
+ ;; Use `expand-file-name'
because curl doesn't
+ ;; expand, e.g. "~" into
"/home/...".
+ (cons "--upload-file"
(expand-file-name filename)))
+ (_ (cons data-arg "@-"))))))
('delete
- (list (cons "--dump-header" "-")
- (cons "--request" (upcase
(symbol-name method)))))
+ (append (list (cons "--dump-header" "-")
+ (cons "--request" (upcase
(symbol-name method))))
+ (pcase as
+ ('file
+ (setf filename
(make-temp-file "plz-"))
+ (list (cons "--output"
filename)))
+ (`(file ,(and (pred stringp)
as-filename))
+ (when (file-exists-p
as-filename)
+ (error "File exists, will
not overwrite: %S" as-filename))
+ (setf filename as-filename)
+ (list (cons "--output"
filename))))))
('head
(list (cons "--head" "")
(cons "--request" "HEAD"))))))
@@ -403,9 +502,9 @@ into the process buffer.
;; default-directory has since been removed). It's unclear what the
best
;; directory is, but this seems to make sense, and it should still
exist.
temporary-file-directory)
- (process-buffer (generate-new-buffer " *plz-request-curl*"))
+ (process-buffer (plz--generate-new-buffer " *plz-request-curl*" t))
(stderr-process (make-pipe-process :name "plz-request-curl-stderr"
- :buffer (generate-new-buffer "
*plz-request-curl-stderr*")
+ :buffer (plz--generate-new-buffer
" *plz-request-curl-stderr*" t)
:noquery t
:sentinel #'plz--stderr-sentinel))
(process (make-process :name "plz-request-curl"
@@ -452,38 +551,11 @@ into the process buffer.
(make-plz-error :message (format
"response is nil for buffer:%S buffer-string:%S"
process-buffer (buffer-string)))))))
('file (lambda ()
- (set-buffer-multibyte nil)
- (plz--narrow-to-body)
- (let ((filename (make-temp-file "plz-")))
- (condition-case err
- (progn
- (write-region (point-min) (point-max) filename)
- (funcall then filename))
- (file-already-exists
- (funcall then (make-plz-error :message (format "error
while writing to file %S: %S" filename err))))
- ;; In case of an error writing to the file, delete the
temp file
- ;; and signal the error. Ignore any errors encountered
while
- ;; deleting the file, which would obscure the original
error.
- (error (ignore-errors
- (delete-file filename))
- (funcall then (make-plz-error :message (format
"error while writing to file %S: %S" filename err))))))))
+ (funcall then filename)))
(`(file ,(and (pred stringp) filename))
+ ;; This requires a separate clause due to the FILENAME binding.
(lambda ()
- (set-buffer-multibyte nil)
- (plz--narrow-to-body)
- (condition-case err
- (progn
- (write-region (point-min) (point-max) filename nil nil nil
'excl)
- (funcall then filename))
- (file-already-exists
- (funcall then (make-plz-error :message (format "error while
writing to file %S: %S" filename err))))
- ;; Since we are creating the file, it seems sensible to delete it
in case of an
- ;; error while writing to it (e.g. a disk-full error). And we
ignore any errors
- ;; encountered while deleting the file, which would obscure the
original error.
- (error (ignore-errors
- (when (file-exists-p filename)
- (delete-file filename)))
- (funcall then (make-plz-error :message (format "error while
writing to file %S: %S" filename err)))))))
+ (funcall then filename)))
((pred functionp) (lambda ()
(let ((coding-system (or (plz--coding-system)
'utf-8)))
(plz--narrow-to-body)
@@ -517,15 +589,19 @@ into the process buffer.
(error "Process unexpectedly nil"))
(while (accept-process-output process))
(while (accept-process-output stderr-process))
+ (plz-debug (float-time) "BEFORE HACK" (process-buffer process))
(when (eq :plz-result (process-get process :plz-result))
+ (plz-debug (float-time) "INSIDE HACK" (process-buffer process))
;; HACK: Sentinel seems to not have been called: call it
again. (Although
;; this is a hack, it seems to be a necessary one due to
Emacs's process
;; handling.) See
<https://github.com/alphapapa/plz.el/issues/3> and
;; <https://debbugs.gnu.org/cgi/bugreport.cgi?bug=50166>.
- (plz--sentinel process "finished\n")
+ (plz--sentinel process "workaround")
+ (plz-debug (float-time) "INSIDE HACK, AFTER CALLING SENTINEL"
(process-buffer process))
(when (eq :plz-result (process-get process :plz-result))
(error "Plz: NO RESULT FROM PROCESS:%S ARGS:%S"
process rest)))
+ (plz-debug (float-time) "AFTER HACK" (process-buffer process))
;; Sentinel seems to have been called: check the result.
(pcase (process-get process :plz-result)
((and (pred plz-error-p) data)
@@ -533,15 +609,15 @@ into the process buffer.
;; into a `plz-error' struct: re-signal the error here,
;; outside of the sentinel.
(if (plz-error-response data)
- ;; FIXME(v0.8): Signal only plz-error.
+ ;; FIXME(v0.10): Signal only plz-error.
(signal 'plz-http-error (list "HTTP error" data))
(signal 'plz-curl-error (list "Curl error" data))))
(else
;; The AS function returned a value: return it.
else)))
(unless (eq as 'buffer)
- (kill-buffer process-buffer))
- (kill-buffer (process-buffer stderr-process)))
+ (plz--kill-buffer process-buffer))
+ (plz--kill-buffer (process-buffer stderr-process)))
;; Async request: return the process object.
process)))
@@ -663,7 +739,7 @@ QUEUE should be a `plz-queue' structure."
(setf (plz-queue-active queue) (delq request
(plz-queue-active queue)))
(plz-run queue))))
(else (lambda (arg)
- ;; FIXME(v0.8): This should be done in `plz-queue'
because
+ ;; FIXME(v0.10): This should be done in `plz-queue'
because
;; `plz-clear' will call the second
queued-request's ELSE
;; before it can be set by `plz-run'.
(unwind-protect
@@ -739,14 +815,31 @@ STATUS should be the process's event string (see info
node `(elisp) Sentinels'). Calls `plz--respond' to process the
HTTP response (directly for synchronous requests, or from a timer
for asynchronous ones)."
- (pcase status
- ((or "finished\n" "killed\n" "interrupt\n"
- (pred numberp)
- (rx "exited abnormally with code " (group (1+ digit))))
- (let ((buffer (process-buffer process)))
- (if (process-get process :plz-sync)
- (plz--respond process buffer status)
- (run-at-time 0 nil #'plz--respond process buffer status))))))
+ (plz-debug (float-time) "BEFORE CONDITION"
+ process status (process-get process :plz-result))
+ (if (eq :plz-result (process-get process :plz-result))
+ ;; Result not yet set: check process status (we call
+ ;; `process-status' because the STATUS argument might not be
+ ;; accurate--see "hack" in `plz').
+ (if (member (process-status process) '(run stop))
+ ;; Process still alive: do nothing.
+ (plz-debug "Doing nothing because:" (process-status process))
+ ;; Process appears to be dead: check STATUS argument.
+ (pcase status
+ ((or "finished\n" "killed\n" "interrupt\n" "workaround"
+ (pred numberp)
+ (rx "exited abnormally with code " (group (1+ digit))))
+ ;; STATUS seems okay: call `plz--respond'.
+ (let ((buffer (process-buffer process)))
+ (if (process-get process :plz-sync)
+ (plz--respond process buffer status)
+ (run-at-time 0 nil #'plz--respond process buffer status))))))
+ ;; Result already set (likely indicating that Emacs did not call
+ ;; the sentinel when `accept-process-output' was called, so we are
+ ;; either being called from our "hack", or being called a second
+ ;; time, after `plz' returned): do nothing.
+ (plz-debug (float-time) ":PLZ-RESULT ALREADY CHANGED"
+ process status (process-get process :plz-result))))
(defun plz--respond (process buffer status)
"Respond to HTTP response from PROCESS in BUFFER.
@@ -759,11 +852,14 @@ argument passed to `plz--sentinel', which see."
;; "Respond" also means "to react to something," which is what this
;; does--react to receiving the HTTP response--and it's an internal
;; name, so why not.
+ (plz-debug (float-time) process status (process-status process) buffer)
(unwind-protect
- (with-current-buffer buffer
- (pcase-exhaustive status
- ((or 0 "finished\n")
- ;; Curl exited normally: check HTTP status code.
+ (pcase-exhaustive (process-exit-status process)
+ (0
+ ;; Curl exited normally: check HTTP status code.
+ (with-current-buffer buffer
+ ;; NOTE: We only switch to the process's buffer if curl
+ ;; exited successfully.
(goto-char (point-min))
(plz--skip-proxy-headers)
(while (plz--skip-redirect-headers))
@@ -776,41 +872,48 @@ argument passed to `plz--sentinel', which see."
;; TODO: If using ":as 'response", the HTTP response
;; should be passed to the THEN function, regardless
;; of the status code. Only for curl errors should
- ;; the ELSE function be called. (Maybe in v0.8.)
+ ;; the ELSE function be called. (Maybe in v0.10.)
;; Any other status code is considered unsuccessful
;; (for now, anyway).
(let ((err (make-plz-error :response (plz--response))))
(pcase-exhaustive (process-get process :plz-else)
(`nil (process-put process :plz-result err))
- ((and (pred functionp) fn) (funcall fn err)))))))
-
- ((or (and (pred numberp) code)
- (rx "exited abnormally with code " (let code (group (1+
digit)))))
- ;; Curl error.
- (let* ((curl-exit-code (cl-typecase code
- (string (string-to-number code))
- (number code)))
- (curl-error-message (alist-get curl-exit-code
plz-curl-errors))
- (err (make-plz-error :curl-error (cons curl-exit-code
curl-error-message))))
- (pcase-exhaustive (process-get process :plz-else)
- (`nil (process-put process :plz-result err))
- ((and (pred functionp) fn) (funcall fn err)))))
-
- ((and (or "killed\n" "interrupt\n") status)
- ;; Curl process killed or interrupted.
- (let* ((message (pcase status
- ("killed\n" "curl process killed")
- ("interrupt\n" "curl process interrupted")))
- (err (make-plz-error :message message)))
- (pcase-exhaustive (process-get process :plz-else)
- (`nil (process-put process :plz-result err))
- ((and (pred functionp) fn) (funcall fn err)))))))
+ ((and (pred functionp) fn) (funcall fn err))))))))
+ ((and code (guard (<= 1 code 90)))
+ ;; Curl exited non-zero.
+ (let* ((curl-exit-code (cl-typecase code
+ (string (string-to-number code))
+ (number code)))
+ (curl-error-message (alist-get curl-exit-code plz-curl-errors))
+ (err (make-plz-error :curl-error (cons curl-exit-code
curl-error-message))))
+ (pcase-exhaustive (process-get process :plz-else)
+ (`nil (process-put process :plz-result err))
+ ((and (pred functionp) fn) (funcall fn err)))))
+ ((and code (guard (not (<= 1 code 90))))
+ ;; If we are here, it should mean that the curl process was
+ ;; killed or interrupted, and the code should be something
+ ;; not (<= 1 code 90).
+ (let* ((message (pcase status
+ ("killed\n" "curl process killed")
+ ("interrupt\n" "curl process interrupted")
+ (_ (format "Unexpected curl process status:%S
code:%S. Please report this bug to the `plz' maintainer." status code))))
+ (err (make-plz-error :message message)))
+ (pcase-exhaustive (process-get process :plz-else)
+ (`nil (process-put process :plz-result err))
+ ((and (pred functionp) fn) (funcall fn err)))))
+ (code
+ ;; If we are here, something is really wrong.
+ (let* ((message (format "Unexpected curl process status:%S code:%S.
Please report this bug to the `plz' maintainer." status code))
+ (err (make-plz-error :message message)))
+ (pcase-exhaustive (process-get process :plz-else)
+ (`nil (process-put process :plz-result err))
+ ((and (pred functionp) fn) (funcall fn err))))))
(when-let ((finally (process-get process :plz-finally)))
(funcall finally))
(unless (or (process-get process :plz-sync)
(eq 'buffer (process-get process :plz-as)))
- (kill-buffer buffer))))
+ (plz--kill-buffer buffer))))
(defun plz--stderr-sentinel (process status)
"Sentinel for STDERR buffer.
@@ -819,7 +922,14 @@ Arguments are PROCESS and STATUS (ok, checkdoc?)."
((or "finished\n" "killed\n" "interrupt\n"
(pred numberp)
(rx "exited abnormally with code " (1+ digit)))
- (kill-buffer (process-buffer process)))))
+ (plz--kill-buffer (process-buffer process)))))
+
+(defun plz--kill-buffer (&optional buffer)
+ "Kill BUFFER unconditionally, without asking for confirmation.
+Binds `kill-buffer-query-functions' to nil."
+ ;; TODO(emacs-28): Remove this workaround when requiring Emacs 28+.
+ (let (kill-buffer-query-functions)
+ (kill-buffer buffer)))
;;;;;; HTTP Responses
- [elpa] externals-release/plz updated (9b681d4893 -> df44acec4b), ELPA Syncer, 2024/06/10
- [elpa] externals-release/plz 4683adb531 4/6: Comment/Docs: Retarget error changes for v0.10, etc., ELPA Syncer, 2024/06/10
- [elpa] externals-release/plz fee8fb47ec 1/6: Change: (plz--kill-buffer) Avoid prompting on Emacs <28, ELPA Syncer, 2024/06/10
- [elpa] externals-release/plz df44acec4b 6/6: Merge: v0.9,
ELPA Syncer <=
- [elpa] externals-release/plz de8554599a 2/6: Docs: Update changelog, ELPA Syncer, 2024/06/10
- [elpa] externals-release/plz 3b04c17824 3/6: Merge: (plz--kill-buffer) Workaround for Emacs < 28, ELPA Syncer, 2024/06/10
- [elpa] externals-release/plz 399ad3e1aa 5/6: Release: v0.9, ELPA Syncer, 2024/06/10