When using EXWM, if PASSWORD-STORE-GET is called and a pinentry
program needs to be executed, Emacs deadlocks. This happens becuase Emacs blocks waiting for output from gpg(1), which is blocked waiting
for output from the pinentry program, which is blocked waiting for
Emacs to manage its window.

This updates PASSWORD-STORE-COPY to work asynchronously. This should be fine, since its primary purpose is side-effecting, and it doesn’t
matter when its evaluation completes.

A new PASSWORD-STORE--RUN-1 function has been added for general cases of async pass(1) commands where the output is needed. While there is an existing PASSWORD-STORE--RUN-ASYNC, it discards output -- it’s only
used for `pass edit', where it’s not needed.  The body of
PASSWORD-STORE--RUN has been replaced with one that uses the async
method, and a wait loop which blocks until it’s complete.

Supporting all this necessitated moving password-store.el to lexical binding and dropping Emacs 24 support. The latter requirement could
be worked around if there are concerns about it.

I’m not sure what the release policy is for this, so I haven’t
incremented the version.

re https://github.com/NicolasPetton/pass#25

diff --git a/contrib/emacs/password-store.el b/contrib/emacs/password-store.el
index 10d4f30..abdf754 100644
--- a/contrib/emacs/password-store.el
+++ b/contrib/emacs/password-store.el
@@ -1,11 +1,11 @@
-;;; password-store.el --- Password store (pass) support
+;;; password-store.el --- Password store (pass) support -*- lexical-binding: t; -*-

;; Copyright (C) 2014-2018 Svend Sorensen <[email protected]>

;; Author: Svend Sorensen <[email protected]>
;; Version: 1.0.2
;; URL: https://www.passwordstore.org/
-;; Package-Requires: ((emacs "24") (f "0.11.0") (s "1.9.0") (with-editor "2.5.11")) +;; Package-Requires: ((emacs "25") (f "0.11.0") (s "1.9.0") (with-editor "2.5.11"))
;; Keywords: tools pass password password-store

;; This file is not part of GNU Emacs.
@@ -59,30 +59,44 @@
      (string-to-number (getenv "PASSWORD_STORE_CLIP_TIME"))
    45))

+(defun password-store--run-1 (callback &rest args)
+  "Run pass with ARGS.
+
+Nil arguments are ignored. Calls CALLBACK with the output on success,
+or outputs error message on failure."
+  (let ((output ""))
+    (make-process
+     :name "password-store-gpg"
+     :command (cons password-store-executable args)
+     :connection-type 'pipe
+     :noquery t
+     :filter (lambda (process text)
+               (setq output (concat output text)))
+     :sentinel (lambda (process state)
+                 (cond
+                  ((string= state "finished\n")
+                   (funcall callback output))
+ ((string= state "open\n") (accept-process-output process)) + (t (error (concat "password-store: " state))))))))
+
(defun password-store--run (&rest args)
  "Run pass with ARGS.

Nil arguments are ignored.  Returns the output on success, or
outputs error message on failure."
-  (with-temp-buffer
-    (let* ((tempfile (make-temp-file ""))
-           (exit-code
-            (apply 'call-process
-                   (append
- (list password-store-executable nil (list t tempfile) nil)
-                    (delq nil args)))))
-      (unless (zerop exit-code)
-        (erase-buffer)
-        (insert-file-contents tempfile))
-      (delete-file tempfile)
-      (if (zerop exit-code)
-          (s-chomp (buffer-string))
-        (error (s-chomp (buffer-string)))))))
+  (let ((output nil)
+        (slept-for 0))
+    (apply #'password-store--run-1 (lambda (password)
+                                     (setq output password))
+           args)
+    (while (not output)
+      (sleep-for .1))
+    output))

(defun password-store--run-async (&rest args)
  "Run pass asynchronously with ARGS.

-Nil arguments are ignored."
+Nil arguments are ignored.  Output is discarded."
  (let ((args (mapcar #'shell-quote-argument args)))
    (with-editor-async-shell-command
     (mapconcat 'identity
@@ -103,9 +117,10 @@ Nil arguments are ignored."
(defun password-store--run-find (&optional string)
  (error "Not implemented"))

-(defun password-store--run-show (entry)
-  (password-store--run "show"
-                       entry))
+(defun password-store--run-show (entry &optional callback)
+  (if callback
+      (password-store--run-1 callback "show" entry)
+    (password-store--run "show" entry)))

(defun password-store--run-insert (entry password &optional force)
  (error "Not implemented"))
@@ -181,11 +196,17 @@ Nil arguments are ignored."
  (password-store--run-edit entry))

;;;###autoload
-(defun password-store-get (entry)
+(defun password-store-get (entry &optional callback)
  "Return password for ENTRY.

-Returns the first line of the password data."
-  (car (s-lines (password-store--run-show entry))))
+Returns the first line of the password data.
+When CALLBACK is non-`NIL', call CALLBACK with the first line instead."
+  (if callback
+      (password-store--run-show
+       entry
+       (lambda (password)
+         (funcall callback (car (s-lines password)))))
+    (car (s-lines (password-store--run-show entry)))))

;;;###autoload
(defun password-store-clear ()
@@ -207,13 +228,15 @@ Clear previous password from kill ring. Pointer to kill ring is stored in `password-store-kill-ring-pointer'. Password is cleared
after `password-store-timeout' seconds."
  (interactive (list (password-store--completing-read)))
-  (let ((password (password-store-get entry)))
-    (password-store-clear)
-    (kill-new password)
- (setq password-store-kill-ring-pointer kill-ring-yank-pointer) - (message "Copied %s to the kill ring. Will clear in %s seconds." entry (password-store-timeout))
-    (setq password-store-timeout-timer
- (run-at-time (password-store-timeout) nil 'password-store-clear))))
+  (password-store-get
+   entry
+   (lambda (password)
+     (password-store-clear)
+     (kill-new password)
+ (setq password-store-kill-ring-pointer kill-ring-yank-pointer) + (message "Copied %s to the kill ring. Will clear in %s seconds." entry (password-store-timeout))
+     (setq password-store-timeout-timer
+ (run-at-time (password-store-timeout) nil 'password-store-clear)))))

;;;###autoload
(defun password-store-init (gpg-id)
_______________________________________________
Password-Store mailing list
[email protected]
https://lists.zx2c4.com/mailman/listinfo/password-store

Reply via email to