branch: elpa/hyperdrive
commit 39683b8d97bd9b30b9869c6413eb20b8d41b128c
Author: Adam Porter <[email protected]>
Commit: Joseph Turner <[email protected]>

    Change: (h/install) Refactor
---
 hyperdrive.el | 124 +++++++++++++++++++++++++++++++++++-----------------------
 1 file changed, 74 insertions(+), 50 deletions(-)

diff --git a/hyperdrive.el b/hyperdrive.el
index 751465988f..64f2e82b59 100644
--- a/hyperdrive.el
+++ b/hyperdrive.el
@@ -1285,61 +1285,72 @@ Intended for relative (i.e. non-full) URLs."
        :sha256 "")))
   "Alist mapping `system-type' to URLs where hyper-gateway-ushin can be 
downloaded.")
 
-;; TODO: Ensure this autoload still works with the closure.
+(defvar h/install-in-progress-p nil
+  "Non-nil while hyperdrive is installing or upgrading the gateway.")
+
 ;;;###autoload
-(let ((install-in-progress-p nil))
-  (defun h/install (&optional forcep)
-    "Install hyper-gateway-ushin.
+(defun h/install (&optional forcep)
+  "Install hyper-gateway-ushin.
 Sets `hyperdrive-gateway-process-type' to \\+`subprocess'.  If
 FORCEP, force downloading and installing of the expected gateway
 version."
-    (interactive)
-    (when install-in-progress-p
-      (user-error "hyper-gateway installation already in progress"))
+  (interactive (list current-prefix-arg))
+  (when h/install-in-progress-p
+    (user-error "hyper-gateway installation already in progress"))
+  (declare-function h//hyper-gateway-ushin-path "hyperdrive-lib")
+  (unless forcep
     (when (h//hyper-gateway-ushin-path)
-      (unless forcep
-        (unless (yes-or-no-p "Program \"hyper-gateway-ushin\" already 
installed.  Reinstall/upgrade? ")
-          (user-error "Not reinstalling/upgrading; aborted"))))
-    (setf install-in-progress-p t)
-    (unwind-protect
-        (pcase-let* (((map :url :sha256) (alist-get system-type 
h/gateway-url-alist))
-                     (local-file-name
-                      (expand-file-name "hyper-gateway-ushin" 
h/gateway-directory))
-                     ;; TODO: Uncomment when SourceHut adds Content-Length 
header.
-                     ;; (file-size
-                     ;;  (file-size-human-readable
-                     ;;   (cl-parse-integer (alist-get 'content-length
-                     ;;                                (plz-response-headers
-                     ;;                                 (plz 'head url :as 
'response))))))
-                     (temp-file-name))
-          (unless (file-directory-p h/gateway-directory)
-            (mkdir h/gateway-directory t))
-          (h/message "Downloading hyper-gateway-ushin..."
-                     ;; (format "Downloading hyper-gateway-ushin (%s)..." 
file-size)
-                     )
-          (let ((inhibit-message t))
-            (setf temp-file-name (url-file-local-copy url)))
-          (unless (equal sha256 (with-temp-buffer
-                                  (insert-file-contents-literally 
temp-file-name)
-                                  (secure-hash 'sha256 (current-buffer))))
-            (h/error "Downloaded hyper-gateway-ushin file hash doesn't match"))
-          (when (file-exists-p local-file-name)
-            (message "Deleting old version: %s" local-file-name)
-            (delete-file local-file-name 'trash))
-          (rename-file temp-file-name local-file-name)
-          (chmod local-file-name #o755)
-          (funcall (get 'h/gateway-process-type 'custom-set)
-                   'h/gateway-process-type 'subprocess)
-          (if (h//gateway-running-p)
-              (progn
-                (when (yes-or-no-p "hyper-gateway-ushin installed.  Restart 
gateway?")
-                  (hyperdrive-stop)
-                  (with-timeout (5 (h/message "Timed out waiting for gateway 
to stop"))
-                    (cl-loop while (h//gateway-running-p)
-                             do (sleep-for 0.2)))
-                  (hyperdrive-start)))
-            (h/message "hyper-gateway-ushin installed.")))
-      (setf install-in-progress-p nil))))
+      (unless (yes-or-no-p "Reinstall/upgrade hyper-gateway-ushin? ")
+        (user-error "Not reinstalling/upgrading; aborted"))))
+  (setf h/install-in-progress-p t)
+  (let ((urls-and-hashes (alist-get system-type h/gateway-url-alist)))
+    (cl-labels
+        ((try ()
+           (if-let ((url-and-hash (pop urls-and-hashes)))
+               (pcase-let (((map :url :sha256) url-and-hash))
+                 (download url sha256))
+             (setf h/install-in-progress-p nil)
+             (h/error "Downloading failed; no more mirrors available")))
+         ;; TODO: Test.
+         (head-size (url)
+           (when-let ((response (ignore-errors (plz 'head url :as 'response))))
+             (cl-parse-integer
+              (alist-get 'content-length (plz-response-headers response)))))
+         (download (url sha256)
+           (plz 'get url :as 'file
+             :then (lambda (filename)
+                     (check filename sha256))
+             :else (lambda (plz-error)
+                     (h/message "Trying next source because downloading 
failed: %S"
+                                plz-error)
+                     (try)))
+           (h/message "Downloading gateway (%s)..."
+                      (or (file-size-human-readable (head-size url))
+                          "unknown size")))
+         (check (file-name sha256)
+           (if (with-temp-buffer
+                 (insert-file-contents-literally file-name)
+                 (equal sha256 (secure-hash 'sha256 (current-buffer))))
+               (then file-name)
+             (try)))
+         (then (file-name)
+           (defvar h/gateway-directory)
+           (let ((destination-name (expand-file-name "hyper-gateway-ushin" 
h/gateway-directory)))
+             (when (file-exists-p destination-name)
+               (move-file-to-trash destination-name))
+             (unless (file-directory-p h/gateway-directory)
+               (mkdir h/gateway-directory t))
+             (rename-file file-name destination-name)
+             (chmod destination-name #o755))
+           ;; NOTE: While `h/gateway-process-type' still exists, this is subtly
+           ;; broken, but we will remove that.
+           ;; FIXME: Remove `h/gateway-process-type' option.
+           (setf h/install-in-progress-p nil)
+           (if (h//gateway-running-p)
+               (when (yes-or-no-p "hyper-gateway-ushin installed.  Restart 
gateway?")
+                 (h/restart))
+             (h/message "hyper-gateway-ushin installed.  Try 
\\[hyperdrive-start]."))))
+      (try))))
 
 (defun h/restart ()
   "Restart the gateway."
@@ -1352,6 +1363,19 @@ version."
   (hyperdrive-start)
   (h/message "Gateway restarted."))
 
+;; (defun h//gateway-appears-valid-p ()
+;;   "Return non-nil if a local installation of the gateway appears valid.
+;; That is, if an executable file exists at the expected location
+;; with an expected hash."
+;;   (when-let ((file-name (h//hyper-gateway-ushin-path)))
+;;     (let* ((file-hash (with-temp-buffer
+;;                          (insert-file-contents-literally file-name)
+;;                          (secure-hash 'sha256 (current-buffer))))
+;;            (urls-and-hashes (alist-get system-type h/gateway-url-alist)))
+;;       (cl-loop for pair in urls-and-hashes
+;;                for expected-hash = (plist-get pair :sha256)
+;;                thereis (equal expected-hash file-hash)))))
+
 ;;;; Footer
 
 (provide 'hyperdrive)

Reply via email to