[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/dtache d0ec7b9777 156/158: Add support for filenotify o
From: |
ELPA Syncer |
Subject: |
[elpa] externals/dtache d0ec7b9777 156/158: Add support for filenotify on macOS |
Date: |
Wed, 19 Jan 2022 18:58:09 -0500 (EST) |
branch: externals/dtache
commit d0ec7b9777575153f0c34ebb27fddb72d6ba9cda
Author: Niklas Eklund <niklas.eklund@posteo.net>
Commit: Niklas Eklund <niklas.eklund@posteo.net>
Add support for filenotify on macOS
The package has been rewritten to watch for changes to the session
directories in order to detect when a session socket is
deleted. Previously the sockets was watched individually.
This change allows dtache to fully support users on macOS, which it
previously couldn't.
---
CHANELOG.org | 1 +
README.org | 4 ++
dtache.el | 113 ++++++++++++++++++++++++----------------------------
test/dtache-test.el | 6 +--
4 files changed, 61 insertions(+), 63 deletions(-)
diff --git a/CHANELOG.org b/CHANELOG.org
index 50eca3a1e9..1c23e826f0 100644
--- a/CHANELOG.org
+++ b/CHANELOG.org
@@ -4,6 +4,7 @@
* Development
+- =dtache= now has full on macOS. The previous issue of not being able to
utilize =filenotify= has been resolved.
- =dtache= now uses =notifications= library to issue notifications by default.
- =dtache= now uses =filenotify= for notifications except on local macOS hosts.
diff --git a/README.org b/README.org
index 13383fadef..ac9c899bcb 100644
--- a/README.org
+++ b/README.org
@@ -345,3 +345,7 @@ I have signed the papers for a
[[https://www.gnu.org/software/emacs/manual/html_
* Credits
I got inspired when reading about =Ambrevar's= pursuits on
[[https://ambrevar.xyz/emacs-eshell/][using eshell as his main shell]]. I
discovered his
[[https://github.com/Ambrevar/dotfiles/blob/master/.emacs.d/lisp/package-eshell-detach.el][package-eshell-detach]]
which got me into the idea of using =dtach= as a base for detached shell
commands.
+
+[[https://gitlab.com/ntdef][Troy de Freitas]] for solving the problem of
getting =dtache= to work with =filenotify= on macOS.
+
+
diff --git a/dtache.el b/dtache.el
index f36d4289a9..1961d592e9 100644
--- a/dtache.el
+++ b/dtache.el
@@ -74,11 +74,6 @@
:type 'string
:group 'dtache)
-(defcustom dtache-timer-configuration '(:seconds 10 :repeat 60 :function
run-with-timer)
- "A property list defining how often to run a timer."
- :type 'plist
- :group 'dtache)
-
(defcustom dtache-env nil
"The name of, or path to, the `dtache' environment script."
:type 'string
@@ -211,6 +206,8 @@ This version is encoded as [package-version].[revision].")
"Sessions are initialized.")
(defvar dtache--sessions nil
"A list of sessions.")
+(defvar dtache--watched-session-directories nil
+ "An alist where values are a (directory . descriptor).")
(defvar dtache--buffer-session nil
"The `dtache-session' session in current buffer.")
(defvar dtache--current-session nil
@@ -514,12 +511,12 @@ compilation or `shell-command' the command will also kill
the window."
:time `(:start ,(time-to-seconds
(current-time)) :end 0.0 :duration 0.0 :offset 0.0)
:status 'unknown
:log-size 0
- :directory (file-name-as-directory
dtache-session-directory)
+ :directory (concat (file-remote-p
default-directory) dtache-session-directory)
:host (dtache--host)
:metadata (dtache-metadata)
:state 'active)))
(dtache--db-insert-entry session)
- (dtache--start-session-monitor session)
+ (dtache--watch-session-directory (dtache--session-directory session))
session)))
(defun dtache-start-session (command &optional suppress-output)
@@ -595,13 +592,15 @@ Optionally SUPPRESS-OUTPUT."
(dtache--update-session session))))
(dtache--db-get-sessions))
- ;; Start monitors
+ ;; Watch session directories
(thread-last (dtache--db-get-sessions)
(seq-filter (lambda (it) (eq 'active (dtache--session-state
it))))
(seq-remove (lambda (it) (when (dtache--session-missing-p it)
(dtache--db-remove-entry it)
t)))
- (seq-do #'dtache--start-session-monitor))
+ (seq-map #'dtache--session-directory)
+ (seq-uniq)
+ (seq-do #'dtache--watch-session-directory))
;; Add `dtache-shell-mode'
(add-hook 'shell-mode-hook #'dtache-shell-mode)))
@@ -820,36 +819,6 @@ Optionally CONCAT the command return command into a
string."
"")
"\n"))
-(defun dtache--session-timer-monitor (session)
- "Configure a timer to monitor SESSION activity.
-The timer object is configured according to `dtache-timer-configuration'."
- (with-connection-local-variables
- (let* ((timer)
- (callback
- (lambda ()
- (when (dtache--state-transition-p session)
- (setf (dtache--session-time session)
- (dtache--update-session-time session t))
- (dtache--session-state-transition-update session)
- (cancel-timer timer)))))
- (setq timer
- (funcall (plist-get dtache-timer-configuration :function)
- (plist-get dtache-timer-configuration :seconds)
- (plist-get dtache-timer-configuration :repeat)
- callback)))))
-
-(defun dtache--session-filenotify-monitor (session)
- "Configure `filenotify' to monitor SESSION activity."
- (file-notify-add-watch
- (dtache--session-file session 'socket)
- '(change)
- (lambda (event)
- (pcase-let ((`(,_ ,action ,_) event))
- (when (eq action 'deleted)
- (setf (dtache--session-time session)
- (dtache--update-session-time session))
- (dtache--session-state-transition-update session))))))
-
(defun dtache--session-deduplicate (sessions)
"Make car of SESSIONS unique by adding an identifier to it."
(let* ((ht (make-hash-table :test #'equal :size (length sessions)))
@@ -865,12 +834,6 @@ The timer object is configured according to
`dtache-timer-configuration'."
(setcar session (format "%s%s" (car session) (make-string
identifier-width ?\s)))))
(seq-reverse reverse-sessions)))
-(defun dtache--session-macos-monitor (session)
- "Configure a timer to monitor SESSION activity on macOS."
- (let ((dtache-timer-configuration
- '(:seconds 0.5 :repeat 0.5 :function run-with-idle-timer)))
- (dtache--session-timer-monitor session)))
-
(defun dtache--decode-session (item)
"Return the session assicated with ITEM."
(cdr (assoc item dtache--session-candidates)))
@@ -914,13 +877,11 @@ Optionally make the path LOCAL to host."
(pcase file
('socket ".socket")
('log ".log"))))
- (remote (file-remote-p (dtache--session-working-directory session)))
- (directory (concat
- remote
- (dtache--session-directory session))))
- (if (and local remote)
- (string-remove-prefix remote (expand-file-name file-name directory))
- (expand-file-name file-name directory))))
+ (remote-local-path (file-remote-p (expand-file-name file-name
(dtache--session-directory session)) 'localname))
+ (full-path (expand-file-name file-name (dtache--session-directory
session))))
+ (if (and local remote-local-path)
+ remote-local-path
+ full-path)))
(defun dtache--cleanup-host-sessions (host)
"Run cleanuup on HOST sessions."
@@ -1131,14 +1092,46 @@ log to deduce the end time."
"Remove `dtache--dtach-detached-message' in STR."
(replace-regexp-in-string (format "\n?%s\n" dtache--dtach-detached-message)
"" str))
-(defun dtache--start-session-monitor (session)
- "Start to monitor SESSION activity."
- (let ((default-directory (dtache--session-working-directory session)))
- (if (and (not(file-remote-p default-directory))
- (eq system-type 'darwin))
- ;; macOS requires a timer based solution
- (dtache--session-macos-monitor session)
- (dtache--session-filenotify-monitor session))))
+(defun dtache--watch-session-directory (session-directory)
+ "Watch for events in SESSION-DIRECTORY."
+ (unless (alist-get session-directory dtache--watched-session-directories
+ nil nil #'string=)
+ (push
+ `(,session-directory . ,(file-notify-add-watch
+ session-directory
+ '(change)
+ #'dtache--session-directory-event))
+ dtache--watched-session-directories)))
+
+(defun dtache--session-directory-event (event)
+ "Act on an EVENT in a directory in `dtache--watched-session-directories'.
+
+If event is caused by the deletion of a socket, locate the related
+session and trigger a state transition."
+ (pcase-let* ((`(,_ ,action ,file) event))
+ (when (and (eq action 'deleted)
+ (string= "socket" (file-name-extension file)))
+ (let* ((id (intern (file-name-base file)))
+ (session (dtache--db-get-session id))
+ (session-directory (dtache--session-directory session)))
+
+ ;; Update session
+ (setf (dtache--session-time session)
+ (dtache--update-session-time session))
+ (dtache--session-state-transition-update session)
+
+ ;; Remove session directory from `dtache--watch-session-directory'
+ ;; if there is no active session associated with the directory
+ (unless
+ (thread-last (dtache--db-get-sessions)
+ (seq-filter (lambda (it) (eq 'active
(dtache--session-state it))))
+ (seq-map #'dtache--session-directory)
+ (seq-uniq)
+ (seq-filter (lambda (it) (string= it
session-directory))))
+ (file-notify-rm-watch
+ (alist-get session-directory dtache--watched-session-directories))
+ (setq dtache--watched-session-directories
+ (assoc-delete-all session-directory
dtache--watched-session-directories)))))))
;;;;; UI
diff --git a/test/dtache-test.el b/test/dtache-test.el
index bb8e58b422..68822aadae 100644
--- a/test/dtache-test.el
+++ b/test/dtache-test.el
@@ -112,15 +112,15 @@
(ert-deftest dtache-test-session-file ()
;; Local files
(cl-letf* (((symbol-function #'expand-file-name) (lambda (file directory)
(concat directory file)))
- ((symbol-function #'file-remote-p) (lambda (_directory) nil))
+ ((symbol-function #'file-remote-p) (lambda (_directory
_localname) "/home/user/tmp"))
(session (dtache--session-create :id 's12345 :directory
"/home/user/tmp/")))
(should (string= "/home/user/tmp/s12345.log" (dtache--session-file session
'log)))
(should (string= "/home/user/tmp/s12345.socket" (dtache--session-file
session 'socket))))
;; Remote files
(cl-letf* (((symbol-function #'expand-file-name) (lambda (file directory)
(concat directory file)))
- ((symbol-function #'file-remote-p) (lambda (_directory)
"/ssh:foo:"))
- (session (dtache--session-create :id 's12345 :directory
"/home/user/tmp/")))
+ ((symbol-function #'file-remote-p) (lambda (_directory
_localname) "/ssh:foo:/home/user/tmp/"))
+ (session (dtache--session-create :id 's12345 :directory
"/ssh:foo:/home/user/tmp/")))
(should (string= "/ssh:foo:/home/user/tmp/s12345.log"
(dtache--session-file session 'log)))
(should (string= "/ssh:foo:/home/user/tmp/s12345.socket"
(dtache--session-file session 'socket)))))
- [elpa] externals/dtache 5831137cf7 101/158: Rename dtache-initialize to dtache-setup, (continued)
- [elpa] externals/dtache 5831137cf7 101/158: Rename dtache-initialize to dtache-setup, ELPA Syncer, 2022/01/19
- [elpa] externals/dtache 9746f4713c 106/158: Rename session-directory to log-directory, ELPA Syncer, 2022/01/19
- [elpa] externals/dtache c6aece77d2 113/158: Enhance dtache-detach-dwim command, ELPA Syncer, 2022/01/19
- [elpa] externals/dtache bf71be0eae 118/158: Change output-size to log-size, ELPA Syncer, 2022/01/19
- [elpa] externals/dtache f77c57f608 120/158: Update duration part 2, ELPA Syncer, 2022/01/19
- [elpa] externals/dtache c8a99aed35 123/158: Add version to the dtache database, ELPA Syncer, 2022/01/19
- [elpa] externals/dtache 4fa1c9e8a2 134/158: Simplify call to dtache--dtach-arg, ELPA Syncer, 2022/01/19
- [elpa] externals/dtache 3942dc6326 135/158: Remove unnecessary checks for dtache-session-mode, ELPA Syncer, 2022/01/19
- [elpa] externals/dtache 3aa5babca5 139/158: Update table formatting, ELPA Syncer, 2022/01/19
- [elpa] externals/dtache ee8f3efa26 144/158: Version 0.3, ELPA Syncer, 2022/01/19
- [elpa] externals/dtache d0ec7b9777 156/158: Add support for filenotify on macOS,
ELPA Syncer <=
- [elpa] externals/dtache aca73c1e60 152/158: Address issues from melpazoid in melpa/melpa7867, ELPA Syncer, 2022/01/19
- [elpa] externals/dtache 81d7fbcdca 082/158: Integrate dtache with start-process, ELPA Syncer, 2022/01/19
- [elpa] externals/dtache 125f100b20 087/158: Regroup variable section, ELPA Syncer, 2022/01/19
- [elpa] externals/dtache 5f12c82fed 090/158: Revert back dtache-eshell, ELPA Syncer, 2022/01/19
- [elpa] externals/dtache 914daabbb8 092/158: Fix regression for shell-command and compile, ELPA Syncer, 2022/01/19
- [elpa] externals/dtache 3029774325 093/158: Update README, ELPA Syncer, 2022/01/19
- [elpa] externals/dtache b779e7071b 104/158: Improve dtache-detach-dwim, ELPA Syncer, 2022/01/19
- [elpa] externals/dtache 051968ec99 111/158: Update dtache extension headers, ELPA Syncer, 2022/01/19
- [elpa] externals/dtache e1ebc053bb 116/158: Avoid saving history file for dtache-shell-command, ELPA Syncer, 2022/01/19
- [elpa] externals/dtache 561f67d075 121/158: Make remove entry delete session log, ELPA Syncer, 2022/01/19