From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mp1 ([2001:41d0:2:aacc::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by ms12 with LMTPS id OCBNHkLNqmBKLwAAsNZ9tg (envelope-from ); Sun, 23 May 2021 21:46:42 +0000 Received: from out2.migadu.com ([2001:41d0:2:aacc::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by mp1 with LMTPS id a+8MCj7NqmCyNAAAbx9fmQ (envelope-from ); Sun, 23 May 2021 21:46:38 +0000 X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kyleam.com; s=key1; t=1621806398; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=o8bA3ce/bXa5MNYuQyvL7W2eatHv4NOkyIbbqlo66l4=; b=q/m7F5ccAMdqt/q3m/+2Hr5QhxBsABkIXJClMoZwYjdztBH9MW8B2nunXfMsZkn0ys79+y UUm0pAhUONg34FIfKpCODPYmjrr4EZAcB6IisU+cY0h0vH8z8QmmlpRik+vHuWx5MpUYPH Nsf9GgL9momBoMS5HuzqhEQORCN+VDlAOgmXYW0TNhN5NoE1JTXMP+PoRA+0ea9lNuEnVa BIr4BUJ1YUHB0+TrMG00ksACx3tE2BaAHg6jwdVO6U4nwfJpgnUJDbUrE62z4SWmW2quaK ngqspzCa22tOLgtxifr9yvcbohIAWkzxjYlEKOEoYD8hf+MQ9lZwcHrQ1Hcv1Q== From: Kyle Meyer To: piem@inbox.kyleam.com Subject: [PATCH 2/5] Rework url-retrieve-synchronously wrapper Date: Sun, 23 May 2021 17:46:20 -0400 Message-Id: <20210523214623.31331-3-kyle@kyleam.com> In-Reply-To: <20210523214623.31331-1-kyle@kyleam.com> References: <20210523214623.31331-1-kyle@kyleam.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Migadu-Flow: FLOW_OUT X-Migadu-Auth-User: kyle@kyleam.com X-TUID: nBvUHzCMVqmF piem-download-and-decompress calls url-retrieve-synchronously, checks for a 200 status, and then manually removes the header. This works okay, but it'd be good for the error handling to match what's done by url-insert-file-contents. Introduce a new macro that largely copies what is done by url-insert-file-contents. The main difference is that url-insert is used instead of url-insert-buffer-contents so that the contents can be inserted literally. This approach is based on Emacs's 5f9671e57e (lisp/emacs-lisp/package.el: Fix decoding of downloaded files, 2019-05-18). --- piem-b4.el | 17 +++++------ piem.el | 88 ++++++++++++++++++++++++++++-------------------------- 2 files changed, 54 insertions(+), 51 deletions(-) diff --git a/piem-b4.el b/piem-b4.el index 48c8bf4..92ddea8 100644 --- a/piem-b4.el +++ b/piem-b4.el @@ -73,15 +73,14 @@ (defun piem-b4--get-am-files (mid coderepo args) ;; back to b4's configuration. (unless local-mbox-p (when-let ((url (and (equal mid (piem-mid)) - (piem-inbox-get :url))) - (buffer (condition-case nil - (piem-download-and-decompress - (concat url (piem-escape-mid mid) "/t.mbox.gz")) - (error nil)))) - (with-current-buffer buffer - (write-region nil nil mbox-thread)) - (kill-buffer buffer) - (setq local-mbox-p t))) + (piem-check-gunzip) + (piem-inbox-get :url)))) + (ignore-errors + (piem-with-url-contents + (concat url (piem-escape-mid mid) "/t.mbox.gz") + (piem-gunzip-buffer) + (write-region nil nil mbox-thread)) + (setq local-mbox-p t)))) ;; Move to the coderepo so that we pick up any b4 configuration ;; from there. (condition-case err diff --git a/piem.el b/piem.el index 78536f1..7b98005 100644 --- a/piem.el +++ b/piem.el @@ -47,9 +47,9 @@ (require 'rfc2047) (require 'subr-x) (require 'transient) (require 'url) +(require 'url-handlers) +(require 'url-http) -(defvar url-http-end-of-headers) -(defvar url-http-response-status) ;;;; Options @@ -535,29 +535,39 @@ (defun piem-check-gunzip () (setq piem--has-gunzip (executable-find "gunzip"))) piem--has-gunzip) -(defun piem--url-remove-header () - (goto-char (1+ url-http-end-of-headers)) - (delete-region (point-min) (point))) - -(defun piem--url-decompress () +(defun piem-gunzip-buffer () + (goto-char (point-min)) (unless (= 0 (call-process-region nil nil "gunzip" nil t)) (error "Decompressing t.mbox.gz failed")) (delete-region (point) (point-max)) (goto-char (point-min))) -(defun piem-download-and-decompress (url) - "Retrieve gzipped content at URL and decompress it. -A buffer with the decompressed content is returned." - (unless (piem-check-gunzip) - (user-error "gunzip executable not found")) - (when-let ((buffer (url-retrieve-synchronously url 'silent))) - (with-current-buffer buffer - (if (/= url-http-response-status 200) - (progn (kill-buffer buffer) - (error "Download of %s failed" url)) - (piem--url-remove-header) - (piem--url-decompress)) - buffer))) +(defmacro piem-with-url-contents (url &rest body) + "Insert URL contents literally into temporary buffer and evaluate BODY." + (declare (indent 1) (debug t)) + (let ((u (cl-gensym "url"))) + `(with-temp-buffer + (set-buffer-multibyte nil) + ;; This mostly copies `url-insert-file-contents', but it embeds + ;; `url-http--insert-file-helper' and uses `url-insert' rather + ;; than `url-insert-buffer-contents' to insert the contents + ;; literally. + (let* ((,u ,url) + (buffer (url-retrieve-synchronously ,u))) + (unless buffer (signal 'file-error (list ,u "No Data"))) + ;; This error handling follows what's in + ;; `url-http--insert-file-helper'. + (with-current-buffer buffer + (when (bound-and-true-p url-http-response-status) + (unless (or (and (>= url-http-response-status 200) + (< url-http-response-status 300)) + (= url-http-response-status 304)) + (let ((desc (nth 2 (assq url-http-response-status url-http-codes)))) + (kill-buffer buffer) + (signal 'file-error (list ,u desc)))))) + (url-insert buffer)) + (goto-char (point-min)) + ,@body))) ;;;; Maildir injection @@ -623,28 +633,22 @@ (defun piem-inject-thread-into-maildir (mid &optional message-only) "Does not look like a Maildir directory: %s" maildir-directory)) ((not (or message-only (piem-check-gunzip))) (user-error "gunzip executable not found"))) - (when-let ((url (concat (piem-mid-url mid) - (if message-only "/raw" "/t.mbox.gz"))) - (buffer (url-retrieve-synchronously url 'silent))) - (unwind-protect - (with-current-buffer buffer - (if (/= url-http-response-status 200) - (error "Download of %s failed" url) - (piem--url-remove-header) - (unless message-only - (piem--url-decompress)) - (pcase-let ((`(,added-count . ,skipped-count) - (piem--write-mbox-to-maildir maildir-directory))) - (message "Added %d message%s%s for %s to %s" - added-count - (if (= added-count 1) "" "s") - (if (> skipped-count 0) - (format " (skipping %d)" skipped-count) - "") - mid - (abbreviate-file-name maildir-directory))) - (run-hook-with-args 'piem-after-mail-injection-functions mid))) - (kill-buffer buffer))))) + (let ((url (concat (piem-mid-url mid) + (if message-only "/raw" "/t.mbox.gz")))) + (piem-with-url-contents url + (unless message-only + (piem-gunzip-buffer)) + (pcase-let ((`(,added-count . ,skipped-count) + (piem--write-mbox-to-maildir maildir-directory))) + (message "Added %d message%s%s for %s to %s" + added-count + (if (= added-count 1) "" "s") + (if (> skipped-count 0) + (format " (skipping %d)" skipped-count) + "") + mid + (abbreviate-file-name maildir-directory)))) + (run-hook-with-args 'piem-after-mail-injection-functions mid)))) ;;;; Patch handling -- 2.31.1