aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhilipp Stephani2018-12-17 21:47:46 +0100
committerPhilipp Stephani2018-12-22 22:10:48 +0100
commit039be4e02513e03ae465efae5694bd4e28a74dbe (patch)
tree34d43f419b279e7f652ef592332f2021b5eedc66
parentb41789f31f2355f6de8c15bbbc10cd6bf3dfe61e (diff)
downloademacs-039be4e02513e03ae465efae5694bd4e28a74dbe.tar.gz
emacs-039be4e02513e03ae465efae5694bd4e28a74dbe.zip
Add file name handler support for 'make-process' (Bug#28691)
* src/process.c (Fmake_process): Add new keyword argument ':file-handler'. (syms_of_process) <make-process, :file-handler>: Define new symbols. * lisp/files.el (file-name-non-special): Add support for 'make-process'. * test/src/process-tests.el (make-process/file-handler/found) (make-process/file-handler/not-found) (make-process/file-handler/disable): New unit tests. (process-tests--file-handler): New helper function. * test/lisp/files-tests.el (files-tests-file-name-non-special-make-process): New unit test. * doc/lispref/files.texi (Magic File Names): Document that 'make-process' can invoke file name handlers. * doc/lispref/processes.texi (Asynchronous Processes): Document ':file-handlers' argument to 'make-process'. * etc/NEWS (Lisp Changes in Emacs 27.1): Mention new :file-handler argument for 'make-process'.
-rw-r--r--doc/lispref/files.texi2
-rw-r--r--doc/lispref/processes.texi10
-rw-r--r--etc/NEWS5
-rw-r--r--lisp/files.el11
-rw-r--r--src/process.c17
-rw-r--r--test/lisp/files-tests.el10
-rw-r--r--test/src/process-tests.el49
7 files changed, 100 insertions, 4 deletions
diff --git a/doc/lispref/files.texi b/doc/lispref/files.texi
index 5b428b6205d..d929978b6ea 100644
--- a/doc/lispref/files.texi
+++ b/doc/lispref/files.texi
@@ -3171,6 +3171,7 @@ first, before handlers for jobs such as remote file access.
3171@code{make-directory}, 3171@code{make-directory},
3172@code{make-directory-internal}, 3172@code{make-directory-internal},
3173@code{make-nearby-temp-file}, 3173@code{make-nearby-temp-file},
3174@code{make-process},
3174@code{make-symbolic-link},@* 3175@code{make-symbolic-link},@*
3175@code{process-file}, 3176@code{process-file},
3176@code{rename-file}, @code{set-file-acl}, @code{set-file-modes}, 3177@code{rename-file}, @code{set-file-acl}, @code{set-file-modes},
@@ -3227,6 +3228,7 @@ first, before handlers for jobs such as remote file access.
3227@code{make-auto-save-file-name}, 3228@code{make-auto-save-file-name},
3228@code{make-direc@discretionary{}{}{}tory}, 3229@code{make-direc@discretionary{}{}{}tory},
3229@code{make-direc@discretionary{}{}{}tory-internal}, 3230@code{make-direc@discretionary{}{}{}tory-internal},
3231@code{make-process},
3230@code{make-symbolic-link}, 3232@code{make-symbolic-link},
3231@code{process-file}, 3233@code{process-file},
3232@code{rename-file}, @code{set-file-acl}, @code{set-file-modes}, 3234@code{rename-file}, @code{set-file-acl}, @code{set-file-modes},
diff --git a/doc/lispref/processes.texi b/doc/lispref/processes.texi
index 402691c6bcf..d72f5b880a2 100644
--- a/doc/lispref/processes.texi
+++ b/doc/lispref/processes.texi
@@ -696,6 +696,12 @@ non-@code{nil} value should be either a buffer or a pipe process
696created with @code{make-pipe-process}, described below. If 696created with @code{make-pipe-process}, described below. If
697@var{stderr} is @code{nil}, standard error is mixed with standard 697@var{stderr} is @code{nil}, standard error is mixed with standard
698output, and both are sent to @var{buffer} or @var{filter}. 698output, and both are sent to @var{buffer} or @var{filter}.
699
700@item :file-handler @var{file-handler}
701If @var{file-handler} is non-@code{nil}, then look for a file name
702handler for the current buffer's @code{default-directory}, and invoke
703that file handler to make the process. If there is no such handler,
704proceed as if @var{file-handler} were @code{nil}.
699@end table 705@end table
700 706
701The original argument list, modified with the actual connection 707The original argument list, modified with the actual connection
@@ -704,8 +710,8 @@ information, is available via the @code{process-contact} function.
704The current working directory of the subprocess is set to the current 710The current working directory of the subprocess is set to the current
705buffer's value of @code{default-directory} if that is local (as 711buffer's value of @code{default-directory} if that is local (as
706determined by `unhandled-file-name-directory'), or "~" otherwise. If 712determined by `unhandled-file-name-directory'), or "~" otherwise. If
707you want to run a process in a remote directory use 713you want to run a process in a remote directory, pass
708@code{start-file-process}. 714@code{:file-handler t} to @code{make-process}.
709@end defun 715@end defun
710 716
711@defun make-pipe-process &rest args 717@defun make-pipe-process &rest args
diff --git a/etc/NEWS b/etc/NEWS
index ea3e4d566f8..253edd593ed 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -1428,6 +1428,11 @@ un-obsoleting it.
1428+++ 1428+++
1429** New function 'group-name' returns a group name corresponding to GID. 1429** New function 'group-name' returns a group name corresponding to GID.
1430 1430
1431** 'make-process' now takes a keyword argument ':file-handler'; if
1432that is non-nil, it will look for a file name handler for the current
1433buffer's 'default-directory' and invoke that file handler to make the
1434process. That way 'make-process' can start remote processes.
1435
1431 1436
1432* Changes in Emacs 27.1 on Non-Free Operating Systems 1437* Changes in Emacs 27.1 on Non-Free Operating Systems
1433 1438
diff --git a/lisp/files.el b/lisp/files.el
index fb6cf0193a9..448df62710c 100644
--- a/lisp/files.el
+++ b/lisp/files.el
@@ -7103,7 +7103,8 @@ only these files will be asked to be saved."
7103 (default-directory 7103 (default-directory
7104 (if (memq operation 7104 (if (memq operation
7105 '(insert-directory process-file start-file-process 7105 '(insert-directory process-file start-file-process
7106 shell-command temporary-file-directory)) 7106 make-process shell-command
7107 temporary-file-directory))
7107 (directory-file-name 7108 (directory-file-name
7108 (expand-file-name 7109 (expand-file-name
7109 (unhandled-file-name-directory default-directory))) 7110 (unhandled-file-name-directory default-directory)))
@@ -7151,7 +7152,13 @@ only these files will be asked to be saved."
7151 ;; These file-notify-* operations take a 7152 ;; These file-notify-* operations take a
7152 ;; descriptor. 7153 ;; descriptor.
7153 (file-notify-rm-watch) 7154 (file-notify-rm-watch)
7154 (file-notify-valid-p))) 7155 (file-notify-valid-p)
7156 ;; `make-process' uses keyword arguments and
7157 ;; doesn't mangle its filenames in any way.
7158 ;; It already strips /: from the binary
7159 ;; filename, so we don't have to do this
7160 ;; here.
7161 (make-process)))
7155 ;; For all other operations, treat the first 7162 ;; For all other operations, treat the first
7156 ;; argument only as the file name. 7163 ;; argument only as the file name.
7157 '(nil 0)))) 7164 '(nil 0))))
diff --git a/src/process.c b/src/process.c
index 8e0b2349f9d..5895f77446b 100644
--- a/src/process.c
+++ b/src/process.c
@@ -1661,6 +1661,11 @@ to the standard error of subprocess. Specifying this implies
1661`:connection-type' is set to `pipe'. If STDERR is nil, standard error 1661`:connection-type' is set to `pipe'. If STDERR is nil, standard error
1662is mixed with standard output and sent to BUFFER or FILTER. 1662is mixed with standard output and sent to BUFFER or FILTER.
1663 1663
1664:file-handler FILE-HANDLER -- If FILE-HANDLER is non-nil, then look
1665for a file name handler for the current buffer's `default-directory'
1666and invoke that file handler to make the process. If there is no
1667such handler, proceed as if FILE-HANDLER were nil.
1668
1664usage: (make-process &rest ARGS) */) 1669usage: (make-process &rest ARGS) */)
1665 (ptrdiff_t nargs, Lisp_Object *args) 1670 (ptrdiff_t nargs, Lisp_Object *args)
1666{ 1671{
@@ -1674,6 +1679,15 @@ usage: (make-process &rest ARGS) */)
1674 /* Save arguments for process-contact and clone-process. */ 1679 /* Save arguments for process-contact and clone-process. */
1675 contact = Flist (nargs, args); 1680 contact = Flist (nargs, args);
1676 1681
1682 if (!NILP (Fplist_get (contact, QCfile_handler)))
1683 {
1684 Lisp_Object file_handler
1685 = Ffind_file_name_handler (BVAR (current_buffer, directory),
1686 Qmake_process);
1687 if (!NILP (file_handler))
1688 return CALLN (Fapply, file_handler, Qmake_process, contact);
1689 }
1690
1677 buffer = Fplist_get (contact, QCbuffer); 1691 buffer = Fplist_get (contact, QCbuffer);
1678 if (!NILP (buffer)) 1692 if (!NILP (buffer))
1679 buffer = Fget_buffer_create (buffer); 1693 buffer = Fget_buffer_create (buffer);
@@ -8098,6 +8112,8 @@ init_process_emacs (int sockfd)
8098void 8112void
8099syms_of_process (void) 8113syms_of_process (void)
8100{ 8114{
8115 DEFSYM (Qmake_process, "make-process");
8116
8101#ifdef subprocesses 8117#ifdef subprocesses
8102 8118
8103 DEFSYM (Qprocessp, "processp"); 8119 DEFSYM (Qprocessp, "processp");
@@ -8138,6 +8154,7 @@ syms_of_process (void)
8138 DEFSYM (Qreal, "real"); 8154 DEFSYM (Qreal, "real");
8139 DEFSYM (Qnetwork, "network"); 8155 DEFSYM (Qnetwork, "network");
8140 DEFSYM (Qserial, "serial"); 8156 DEFSYM (Qserial, "serial");
8157 DEFSYM (QCfile_handler, ":file-handler");
8141 DEFSYM (QCbuffer, ":buffer"); 8158 DEFSYM (QCbuffer, ":buffer");
8142 DEFSYM (QChost, ":host"); 8159 DEFSYM (QChost, ":host");
8143 DEFSYM (QCservice, ":service"); 8160 DEFSYM (QCservice, ":service");
diff --git a/test/lisp/files-tests.el b/test/lisp/files-tests.el
index 3b192ee8727..9d827e865d9 100644
--- a/test/lisp/files-tests.el
+++ b/test/lisp/files-tests.el
@@ -1109,6 +1109,16 @@ unquoted file names."
1109 (with-temp-buffer 1109 (with-temp-buffer
1110 (write-region nil nil nospecial nil :visit)))) 1110 (write-region nil nil nospecial nil :visit))))
1111 1111
1112(ert-deftest files-tests-file-name-non-special-make-process ()
1113 "Check that the ‘:file-handler’ argument of ‘make-process’
1114works as expected if the default directory is quoted."
1115 (let ((default-directory (file-name-quote invocation-directory))
1116 (program (file-name-quote
1117 (expand-file-name invocation-name invocation-directory))))
1118 (should (processp (make-process :name "name"
1119 :command (list program "--version")
1120 :file-handler t)))))
1121
1112(ert-deftest files-tests--insert-directory-wildcard-in-dir-p () 1122(ert-deftest files-tests--insert-directory-wildcard-in-dir-p ()
1113 (let ((alist (list (cons "/home/user/*/.txt" (cons "/home/user/" "*/.txt")) 1123 (let ((alist (list (cons "/home/user/*/.txt" (cons "/home/user/" "*/.txt"))
1114 (cons "/home/user/.txt" nil) 1124 (cons "/home/user/.txt" nil)
diff --git a/test/src/process-tests.el b/test/src/process-tests.el
index 551b34ff371..af5bc737574 100644
--- a/test/src/process-tests.el
+++ b/test/src/process-tests.el
@@ -215,5 +215,54 @@
215 (string-to-list "stdout\n") 215 (string-to-list "stdout\n")
216 (string-to-list "stderr\n")))))) 216 (string-to-list "stderr\n"))))))
217 217
218(ert-deftest make-process/file-handler/found ()
219 "Check that the ‘:file-handler’ argument of ‘make-process’
220works as expected if a file handler is found."
221 (let ((file-handler-calls 0))
222 (cl-flet ((file-handler
223 (&rest args)
224 (should (equal default-directory "test-handler:/dir/"))
225 (should (equal args '(make-process :name "name"
226 :command ("/some/binary")
227 :file-handler t)))
228 (cl-incf file-handler-calls)
229 'fake-process))
230 (let ((file-name-handler-alist (list (cons (rx bos "test-handler:")
231 #'file-handler)))
232 (default-directory "test-handler:/dir/"))
233 (should (eq (make-process :name "name"
234 :command '("/some/binary")
235 :file-handler t)
236 'fake-process))
237 (should (= file-handler-calls 1))))))
238
239(ert-deftest make-process/file-handler/not-found ()
240 "Check that the ‘:file-handler’ argument of ‘make-process’
241works as expected if no file handler is found."
242 (let ((file-name-handler-alist ())
243 (default-directory invocation-directory)
244 (program (expand-file-name invocation-name invocation-directory)))
245 (should (processp (make-process :name "name"
246 :command (list program "--version")
247 :file-handler t)))))
248
249(ert-deftest make-process/file-handler/disable ()
250 "Check ‘make-process’ works as expected if it shouldn’t use the
251file handler."
252 (let ((file-name-handler-alist (list (cons (rx bos "test-handler:")
253 #'process-tests--file-handler)))
254 (default-directory "test-handler:/dir/")
255 (program (expand-file-name invocation-name invocation-directory)))
256 (should (processp (make-process :name "name"
257 :command (list program "--version"))))))
258
259(defun process-tests--file-handler (operation &rest _args)
260 (cl-ecase operation
261 (unhandled-file-name-directory "/")
262 (make-process (ert-fail "file handler called unexpectedly"))))
263
264(put #'process-tests--file-handler 'operations
265 '(unhandled-file-name-directory make-process))
266
218(provide 'process-tests) 267(provide 'process-tests)
219;; process-tests.el ends here. 268;; process-tests.el ends here.