diff options
author | Michael Albinus <michael.albinus@gmx.de> | 2019-03-09 16:44:24 +0100 |
---|---|---|
committer | Michael Albinus <michael.albinus@gmx.de> | 2019-03-09 16:44:24 +0100 |
commit | 21f54feee8c83e2c5fd8eeb6741cbd479a7b19eb (patch) | |
tree | 3edf223c49dfedf09ec93804856954a9554a93cd | |
parent | c37bdd00c7dcabaa3ca8405d9dc5122ed36f27e0 (diff) | |
download | emacs-21f54feee8c83e2c5fd8eeb6741cbd479a7b19eb.tar.gz |
Do not hardcode "/bin/sh" in compile. Bug#24338, Bug#29723
* doc/emacs/custom.texi (Connection Variables): New node.
* doc/emacs/emacs.texi (Top): Add entry for Connection Variables.
* doc/emacs/misc.texi (Single Shell): Mention default value for
remote buffers.
* doc/lispref/variables.texi (Connection Local Variables):
Describe `with-connection-local-variables' instead of
`with-connection-local-profiles'.
* doc/misc/tramp.texi (Remote processes): Refer to Emacs manual.
Mention default connection-local settings for `shell-file-name'
and `shell-command-switch'.
* etc/NEWS: Mention connection-local variables changes.
* lisp/files-x.el (hack-connection-local-variables):
Push connection-local variables to `file-local-variables-alist'.
(connection-local-criteria-for-default-directory): New defsubst.
(with-connection-local-variables): Rename from
`with-connection-local-profiles'. Adapt implementation.
* lisp/files.el (hack-local-variables):
Call `hack-connection-local-variables'.
* lisp/shell.el (shell): Use `with-connection-local-variables'.
* lisp/subr.el (start-file-process-shell-command):
* lisp/progmodes/compile.el (compilation-start):
Use `with-connection-local-variables'. Do not set "/bin/sh" for
remote buffers, trust settings of `shell-file-name'. (Bug#24338),
(Bug#29723)
* lisp/net/ange-ftp.el (ange-ftp-compress, ange-ftp-uncompress):
Use `shell-command-switch'.
* lisp/net/tramp-adb.el (tramp-adb-connection-local-default-profile):
New defvar. Add it to connection-local profiles after loading "shell".
* lisp/net/tramp-integration.el (tramp-compat): Require tramp-compat.
(tramp-compat-exec-path): Do not declare anymore.
(tramp-connection-local-safe-shell-file-names): New defvar.
(tramp-connection-local-default-profile): New defconst. Activate
it after loading "shell".
(shell-file-name, shell-command-switch): Add safe-local-variable
property.
* lisp/net/tramp-sh.el (tramp-display-escape-sequence-regexp):
Add tramp-autoload cookie.
* test/lisp/files-x-tests.el (remote-shell-file-name):
Add safe-local-variable property to remote-* variables.
(tramp-connection-local-default-profile): Declare.
(files-x-test-with-connection-local-variables):
Rename from `files-x-test-with-connection-local-profiles'. Adapt
implementation.
* test/lisp/net/tramp-tests.el
(tramp-test34-connection-local-variables): New test.
(tramp-test34-explicit-shell-file-name): Run it also for tramp-adb.
Bind connection-local-{profile,criteria}-alist. Use tramp-adb
specific `shell-file-name'. Add safe-local-variable property to
`explicit-shell-file-name' and `explicit-sh-args'.
-rw-r--r-- | doc/emacs/custom.texi | 48 | ||||
-rw-r--r-- | doc/emacs/emacs.texi | 2 | ||||
-rw-r--r-- | doc/emacs/misc.texi | 4 | ||||
-rw-r--r-- | doc/lispref/variables.texi | 17 | ||||
-rw-r--r-- | doc/misc/tramp.texi | 10 | ||||
-rw-r--r-- | etc/NEWS | 16 | ||||
-rw-r--r-- | lisp/files-x.el | 51 | ||||
-rw-r--r-- | lisp/files.el | 5 | ||||
-rw-r--r-- | lisp/net/ange-ftp.el | 4 | ||||
-rw-r--r-- | lisp/net/tramp-adb.el | 20 | ||||
-rw-r--r-- | lisp/net/tramp-integration.el | 34 | ||||
-rw-r--r-- | lisp/net/tramp-sh.el | 1 | ||||
-rw-r--r-- | lisp/progmodes/compile.el | 19 | ||||
-rw-r--r-- | lisp/shell.el | 27 | ||||
-rw-r--r-- | lisp/subr.el | 11 | ||||
-rw-r--r-- | test/lisp/files-x-tests.el | 89 | ||||
-rw-r--r-- | test/lisp/net/tramp-tests.el | 77 |
17 files changed, 334 insertions, 101 deletions
diff --git a/doc/emacs/custom.texi b/doc/emacs/custom.texi index 474149fcae6..c649c170293 100644 --- a/doc/emacs/custom.texi +++ b/doc/emacs/custom.texi @@ -765,6 +765,8 @@ expects (@pxref{Examining}). * Locals:: Per-buffer values of variables. * File Variables:: How files can specify variable values. * Directory Variables:: How variable values can be specified by directory. +* Connection Variables:: Variables which are valid for buffers with a + remote default directory. @end menu @node Examining @@ -1421,6 +1423,52 @@ variables are handled in the same way as unsafe file-local variables do not visit a file directly but perform work within a directory, such as Dired buffers (@pxref{Dired}). +@node Connection Variables +@subsection Per-Connection Local Variables +@cindex local variables, for all remote connections +@cindex connection-local variables +@cindex per-connection local variables + + Most of the variables reflect the situation on the local machine. +Often, they must use a different value when you operate in buffers +with a remote default directory. Think about the shell to be applied +when calling @code{shell} -- it might be @file{/bin/bash} on your +local machine, and @file{/bin/ksh} on a remote machine. + + This can be accomplished with @dfn{connection-local variables}. +Directory and file local variables override connection-local +variables. Unsafe connection-local variables are handled in the same +way as unsafe file-local variables (@pxref{Safe File Variables}). + +@findex connection-local-set-profile-variables +@findex connection-local-set-profiles + Connection-local variables are declared as a group of +variables/value pairs in a @dfn{profile}, using the +@code{connection-local-set-profile-variables} function. The function +@code{connection-local-set-profiles} activates profiles for a given +criteria, identifying a remote machine: + +@example +(connection-local-set-profile-variables 'remote-ksh + '((shell-file-name . "/bin/ksh") + (shell-command-switch . "-c"))) + +(connection-local-set-profile-variables 'remote-bash + '((shell-file-name . "/bin/bash") + (shell-command-switch . "-c"))) + +(connection-local-set-profiles + '(:application tramp :machine "remotemachine") 'remote-ksh) +@end example + + This code declares two different profiles, @code{remote-ksh} and +@code{remote-bash}. The profile @code{remote-ksh} is applied to all +buffers which have a remote default directory matching the regexp +@code{"remotemachine} as host name. Such a criteria can also +discriminate for the properties @code{:protocol} (this is the Tramp +method) or @code{:user} (a remote user name). The @code{nil} criteria +matches all buffers with a remote default directory. + @node Key Bindings @section Customizing Key Bindings @cindex key bindings diff --git a/doc/emacs/emacs.texi b/doc/emacs/emacs.texi index 950ddc01123..7edc1a5fae1 100644 --- a/doc/emacs/emacs.texi +++ b/doc/emacs/emacs.texi @@ -1135,6 +1135,8 @@ Variables * Locals:: Per-buffer values of variables. * File Variables:: How files can specify variable values. * Directory Variables:: How variable values can be specified by directory. +* Connection Variables:: Variables which are valid for buffers with a + remote default directory. Local Variables in Files diff --git a/doc/emacs/misc.texi b/doc/emacs/misc.texi index a3aa71e2672..7d7065a441a 100644 --- a/doc/emacs/misc.texi +++ b/doc/emacs/misc.texi @@ -795,6 +795,10 @@ to @command{gpg}. This will output the list of keys to the name is relative, Emacs searches the directories listed in @code{exec-path} (@pxref{Shell}). + If the default directory is remote (@pxref{Remote Files}), the +default value is @file{/bin/sh}. This can be changed by declaring +@code{shell-file-name} connection-local (@pxref{Connection Variables}). + To specify a coding system for @kbd{M-!} or @kbd{M-|}, use the command @kbd{C-x @key{RET} c} immediately beforehand. @xref{Communication Coding}. diff --git a/doc/lispref/variables.texi b/doc/lispref/variables.texi index f1e0e37e6d6..aca7d2f5e93 100644 --- a/doc/lispref/variables.texi +++ b/doc/lispref/variables.texi @@ -2191,9 +2191,9 @@ This function looks for connection-local variables according to @var{criteria}, and immediately applies them in the current buffer. @end defun -@defmac with-connection-local-profiles profiles &rest body -All connection-local variables, which are specified by a connection -profile in @var{profiles}, are applied. +@defmac with-connection-local-variables &rest body +All connection-local variables, which are specified by +@code{default-directory}, are applied. After that, @var{body} is executed, and the connection-local variables are unwound. Example: @@ -2207,8 +2207,15 @@ are unwound. Example: @end group @group -(with-connection-local-profiles '(remote-perl) - do something useful) +(connection-local-set-profiles + '(:application 'tramp :protocol "ssh" :machine "remotehost") + 'remote-perl) +@end group + +@group +(let ((default-directory "/ssh:remotehost:/working/dir/")) + (with-connection-local-variables + do something useful)) @end group @end example @end defmac diff --git a/doc/misc/tramp.texi b/doc/misc/tramp.texi index db3b3f7fee5..ea6ad15dc3d 100644 --- a/doc/misc/tramp.texi +++ b/doc/misc/tramp.texi @@ -2970,7 +2970,7 @@ Starting with Emacs 26, you could use connection-local variables for setting different values of @code{explicit-shell-file-name} for different remote hosts. @ifinfo -@pxref{Connection Local Variables, , , elisp} +@xref{Connection Variables, , , emacs} @end ifinfo @lisp @@ -3023,6 +3023,14 @@ host. Example: @kbd{M-x auto-revert-tail-mode @key{RET}} runs similarly showing continuous output. +@code{shell-command} uses the variables @code{shell-file-name} and +@code{shell-command-switch} in order to determine which shell to run. +For remote hosts, their default values are @file{/bin/sh} and +@option{-c}, respectively (except for the @option{adb} method, which +uses @file{/system/bin/sh}). Like the variables in the previous +section, these variables can be changed via connection-local +variables. + @subsection Running @code{eshell} on a remote host @cindex @code{eshell} @@ -279,6 +279,17 @@ matches strings where the pattern appears as a subsequence. Put simply, makes "foo" complete to both "barfoo" and "frodo". Add 'flex' to 'completion-styles' or 'completion-category-overrides' to use it. +** Connection-local variables + ++++ +*** Connection-local variables are applied by default like file-local +and directory-local variables. + ++++ +*** The macro 'with-connection-local-variables' has been renamed from +'with-connection-local-profiles'. No argument 'profiles' needed any +longer. + * Editing Changes in Emacs 27.1 @@ -994,7 +1005,12 @@ followed when Emacs writes the relevant history variables to the disk. --- *** Program name completion inside remote shells works now as expected. ++++ +*** The variable 'shell-file-name' can be set now as connection-local +variable for remote shells. It still defaults to "/bin/sh". + ** Pcomplete + *** The function 'pcomplete-uniquify-list' has been renamed from 'pcomplete-uniqify-list'. diff --git a/lisp/files-x.el b/lisp/files-x.el index c9abb695700..eedf630b71f 100644 --- a/lisp/files-x.el +++ b/lisp/files-x.el @@ -582,7 +582,7 @@ changed by the user.") (setq ignored-local-variables (cons 'connection-local-variables-alist ignored-local-variables)) -(defvar connection-local-profile-alist '() +(defvar connection-local-profile-alist nil "Alist mapping connection profiles to variable lists. Each element in this list has the form (PROFILE VARIABLES). PROFILE is the name of a connection profile (a symbol). @@ -590,7 +590,7 @@ VARIABLES is a list that declares connection-local variables for PROFILE. An element in VARIABLES is an alist whose elements are of the form (VAR . VALUE).") -(defvar connection-local-criteria-alist '() +(defvar connection-local-criteria-alist nil "Alist mapping connection criteria to connection profiles. Each element in this list has the form (CRITERIA PROFILES). CRITERIA is a plist identifying a connection and the application @@ -685,7 +685,9 @@ This does nothing if `enable-connection-local-variables' is nil." ;; Loop over variables. (dolist (variable (connection-local-get-profile-variables profile)) (unless (assq (car variable) connection-local-variables-alist) - (push variable connection-local-variables-alist)))))) + (push variable connection-local-variables-alist)))) + ;; Push them to `file-local-variables-alist'. + (hack-local-variables-filter connection-local-variables-alist nil))) ;;;###autoload (defun hack-connection-local-variables-apply (criteria) @@ -697,24 +699,35 @@ will not be changed." (copy-tree connection-local-variables-alist))) (hack-local-variables-apply))) +(defsubst connection-local-criteria-for-default-directory () + "Return a connection-local criteria, which represents `default-directory'." + (when (file-remote-p default-directory) + `(:application tramp + :protocol ,(file-remote-p default-directory 'method) + :user ,(file-remote-p default-directory 'user) + :machine ,(file-remote-p default-directory 'host)))) + ;;;###autoload -(defmacro with-connection-local-profiles (profiles &rest body) - "Apply connection-local variables according to PROFILES in current buffer. +(defmacro with-connection-local-variables (&rest body) + "Apply connection-local variables according to `default-directory'. Execute BODY, and unwind connection-local variables." - (declare (indent 1) (debug t)) - `(let ((enable-connection-local-variables t) - (old-buffer-local-variables (buffer-local-variables)) - connection-local-variables-alist connection-local-criteria-alist) - (apply 'connection-local-set-profiles nil ,profiles) - (hack-connection-local-variables-apply nil) - (unwind-protect - (progn ,@body) - ;; Cleanup. - (dolist (variable connection-local-variables-alist) - (let ((elt (assq (car variable) old-buffer-local-variables))) - (if elt - (set (make-local-variable (car elt)) (cdr elt)) - (kill-local-variable (car variable)))))))) + (declare (debug t)) + `(if (file-remote-p default-directory) + (let ((enable-connection-local-variables t) + (old-buffer-local-variables (buffer-local-variables)) + connection-local-variables-alist) + (hack-connection-local-variables-apply + (connection-local-criteria-for-default-directory)) + (unwind-protect + (progn ,@body) + ;; Cleanup. + (dolist (variable connection-local-variables-alist) + (let ((elt (assq (car variable) old-buffer-local-variables))) + (if elt + (set (make-local-variable (car elt)) (cdr elt)) + (kill-local-variable (car variable))))))) + ;; No connection-local variables to apply. + ,@body)) diff --git a/lisp/files.el b/lisp/files.el index 9948bd4a034..77a194b085d 100644 --- a/lisp/files.el +++ b/lisp/files.el @@ -3590,6 +3590,11 @@ local variables, but directory-local variables may still be applied." result) (unless (eq handle-mode t) (setq file-local-variables-alist nil) + (when (file-remote-p default-directory) + (with-demoted-errors "Connection-local variables error: %s" + ;; Note this is a no-op if enable-local-variables is nil. + (hack-connection-local-variables + (connection-local-criteria-for-default-directory)))) (with-demoted-errors "Directory-local variables error: %s" ;; Note this is a no-op if enable-local-variables is nil. (hack-dir-local-variables))) diff --git a/lisp/net/ange-ftp.el b/lisp/net/ange-ftp.el index 428bf32947b..5af9ea75ed1 100644 --- a/lisp/net/ange-ftp.el +++ b/lisp/net/ange-ftp.el @@ -4277,7 +4277,7 @@ NEWNAME should be the name to give the new compressed or uncompressed file.") nil t nil - "-c" + shell-command-switch (format "compress -f -c < %s > %s" tmp1 tmp2)) (and ange-ftp-process-verbose (ange-ftp-message "Compressing %s...done" abbr)) @@ -4313,7 +4313,7 @@ NEWNAME should be the name to give the new compressed or uncompressed file.") nil t nil - "-c" + shell-command-switch (format "uncompress -c < %s > %s" tmp1 tmp2)) (and ange-ftp-process-verbose (ange-ftp-message "Uncompressing %s...done" abbr)) diff --git a/lisp/net/tramp-adb.el b/lisp/net/tramp-adb.el index eb3295ee352..b40e69ef634 100644 --- a/lisp/net/tramp-adb.el +++ b/lisp/net/tramp-adb.el @@ -1370,6 +1370,26 @@ connection if a previous connection has died for some reason." ;; Mark it as connected. (tramp-set-connection-property p "connected" t))))))) +;; Default settings for connection-local variables. +(defconst tramp-adb-connection-local-default-profile + '((shell-file-name . "/system/bin/sh") + (shell-command-switch . "-c")) + "Default connection-local variables for remote adb connections.") +(add-to-list 'tramp-connection-local-safe-shell-file-names "/system/bin/sh") + +;; `connection-local-set-profile-variables' and +;; `connection-local-set-profiles' exists since Emacs 26.1. +(eval-after-load "shell" + '(progn + (tramp-compat-funcall + 'connection-local-set-profile-variables + 'tramp-adb-connection-local-default-profile + tramp-adb-connection-local-default-profile) + (tramp-compat-funcall + 'connection-local-set-profiles + `(:application tramp :protocol ,tramp-adb-method) + 'tramp-adb-connection-local-default-profile))) + (add-hook 'tramp-unload-hook (lambda () (unload-feature 'tramp-adb 'force))) diff --git a/lisp/net/tramp-integration.el b/lisp/net/tramp-integration.el index 2a461763480..946d7f8cbab 100644 --- a/lisp/net/tramp-integration.el +++ b/lisp/net/tramp-integration.el @@ -27,9 +27,10 @@ ;;; Code: +(require 'tramp-compat) + ;; Pacify byte-compiler. (require 'cl-lib) -(declare-function tramp-compat-exec-path "tramp") (declare-function tramp-dissect-file-name "tramp") (declare-function tramp-file-name-equal-p "tramp") (declare-function tramp-tramp-file-p "tramp") @@ -170,6 +171,37 @@ NAME must be equal to `tramp-current-connection'." (remove-hook 'tramp-cleanup-all-connections-hook #'tramp-recentf-cleanup-all))))) +;;; Default connection-local variables for Tramp: + +;;;###tramp-autoload +(defvar tramp-connection-local-safe-shell-file-names nil + "List of safe `shell-file-name' values for remote hosts.") +(add-to-list 'tramp-connection-local-safe-shell-file-names "/bin/sh") + +(defconst tramp-connection-local-default-profile + '((shell-file-name . "/bin/sh") + (shell-command-switch . "-c")) + "Default connection-local variables for remote connections.") +(put 'shell-file-name 'safe-local-variable + (lambda (item) + (and (stringp item) + (member item tramp-connection-local-safe-shell-file-names)))) +(put 'shell-command-switch 'safe-local-variable + (lambda (item) (and (stringp item) (string-equal item "-c")))) + +;; `connection-local-set-profile-variables' and +;; `connection-local-set-profiles' exists since Emacs 26.1. +(eval-after-load "shell" + '(progn + (tramp-compat-funcall + 'connection-local-set-profile-variables + 'tramp-connection-local-default-profile + tramp-connection-local-default-profile) + (tramp-compat-funcall + 'connection-local-set-profiles + `(:application tramp) + 'tramp-connection-local-default-profile))) + (add-hook 'tramp-unload-hook (lambda () (unload-feature 'tramp-integration 'force))) diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el index ee16138f700..d9edcb14198 100644 --- a/lisp/net/tramp-sh.el +++ b/lisp/net/tramp-sh.el @@ -81,6 +81,7 @@ the default storage location, e.g. \"$HOME/.sh_history\"." (const :tag "Unset HISTFILE" t) (string :tag "Redirect to a file"))) +;;;###tramp-autoload (defconst tramp-display-escape-sequence-regexp "\e[[;0-9]+m" "Terminal control escape sequences for display attributes.") diff --git a/lisp/progmodes/compile.el b/lisp/progmodes/compile.el index b3f32c82316..3650b05607c 100644 --- a/lisp/progmodes/compile.el +++ b/lisp/progmodes/compile.el @@ -1754,15 +1754,16 @@ Returns the compilation buffer created." (if (fboundp 'make-process) (let ((proc (if (eq mode t) - ;; comint uses `start-file-process'. - (get-buffer-process - (with-no-warnings - (comint-exec - outbuf (downcase mode-name) - (if (file-remote-p default-directory) - "/bin/sh" - shell-file-name) - nil `("-c" ,command)))) + ;; On remote hosts, the local `shell-file-name' + ;; might be useless. + (with-connection-local-variables + ;; comint uses `start-file-process'. + (get-buffer-process + (with-no-warnings + (comint-exec + outbuf (downcase mode-name) + shell-file-name + nil `(,shell-command-switch ,command))))) (start-file-process-shell-command (downcase mode-name) outbuf command)))) ;; Make the buffer's mode line show process state. diff --git a/lisp/shell.el b/lisp/shell.el index 524a8848840..8a2d4489b8a 100644 --- a/lisp/shell.el +++ b/lisp/shell.el @@ -99,6 +99,7 @@ (require 'comint) (require 'pcomplete) +(eval-when-compile (require 'files-x)) ;with-connection-local-variables ;;; Customization and Buffer Variables @@ -721,23 +722,17 @@ Otherwise, one argument `-i' is passed to the shell. (with-current-buffer buffer (when (file-remote-p default-directory) - ;; Apply connection-local variables. - (hack-connection-local-variables-apply - `(:application tramp - :protocol ,(file-remote-p default-directory 'method) - :user ,(file-remote-p default-directory 'user) - :machine ,(file-remote-p default-directory 'host))) - ;; On remote hosts, the local `shell-file-name' might be useless. - (if (and (called-interactively-p 'any) - (null explicit-shell-file-name) - (null (getenv "ESHELL"))) - (set (make-local-variable 'explicit-shell-file-name) - (file-local-name - (expand-file-name - (read-file-name - "Remote shell path: " default-directory shell-file-name - t shell-file-name))))))) + (with-connection-local-variables + (if (and (called-interactively-p 'any) + (null explicit-shell-file-name) + (null (getenv "ESHELL"))) + (set (make-local-variable 'explicit-shell-file-name) + (file-local-name + (expand-file-name + (read-file-name + "Remote shell path: " default-directory shell-file-name + t shell-file-name)))))))) ;; The buffer's window must be correctly set when we call comint ;; (so that comint sets the COLUMNS env var properly). diff --git a/lisp/subr.el b/lisp/subr.el index 5b0330745fa..4024c68e68d 100644 --- a/lisp/subr.el +++ b/lisp/subr.el @@ -3185,11 +3185,12 @@ discouraged." "Start a program in a subprocess. Return the process object for it. Similar to `start-process-shell-command', but calls `start-file-process'." (declare (advertised-calling-convention (name buffer command) "23.1")) - (start-file-process - name buffer - (if (file-remote-p default-directory) "/bin/sh" shell-file-name) - (if (file-remote-p default-directory) "-c" shell-command-switch) - (mapconcat 'identity args " "))) + ;; On remote hosts, the local `shell-file-name' might be useless. + (with-connection-local-variables + (start-file-process + name buffer + shell-file-name shell-command-switch + (mapconcat 'identity args " ")))) (defun call-process-shell-command (command &optional infile buffer display &rest args) diff --git a/test/lisp/files-x-tests.el b/test/lisp/files-x-tests.el index d678be409d1..568a8984479 100644 --- a/test/lisp/files-x-tests.el +++ b/test/lisp/files-x-tests.el @@ -35,6 +35,11 @@ '((remote-null-device . "/dev/null"))) (defconst files-x-test--variables4 '((remote-null-device . "null"))) +(put 'remote-shell-file-name 'safe-local-variable #'identity) +(put 'remote-shell-command-switch 'safe-local-variable #'identity) +(put 'remote-shell-interactive-switch 'safe-local-variable #'identity) +(put 'remote-shell-login-switch 'safe-local-variable #'identity) +(put 'remote-null-device 'safe-local-variable #'identity) (defconst files-x-test--application '(:application 'my-application)) (defconst files-x-test--another-application @@ -268,7 +273,9 @@ (should-not (local-variable-p 'remote-shell-file-name)) (should-not (boundp 'remote-shell-file-name)))))) -(ert-deftest files-x-test-with-connection-local-profiles () +(defvar tramp-connection-local-default-profile) + +(ert-deftest files-x-test-with-connection-local-variables () "Test setting connection-local variables." (let (connection-local-profile-alist connection-local-criteria-alist) @@ -303,46 +310,48 @@ (string-equal (symbol-value 'remote-null-device) "/dev/null")) ;; A candidate connection-local variable is not bound yet. - (should-not (local-variable-p 'remote-shell-command-switch)) - - ;; Use the macro. - (with-connection-local-profiles '(remote-bash remote-ksh) - ;; All connection-local variables are set. They apply in - ;; reverse order in `connection-local-variables-alist'. - ;; This variable keeps only the variables to be set inside - ;; the macro. - (should - (equal connection-local-variables-alist - (nreverse (copy-tree files-x-test--variables1)))) - ;; The variables exist also as local variables. - (should (local-variable-p 'remote-shell-file-name)) - (should (local-variable-p 'remote-shell-command-switch)) - ;; The proper variable values are set. The settings from - ;; `remote-bash' overwrite the same variables as in - ;; `remote-ksh'. - (should - (string-equal (symbol-value 'remote-shell-file-name) "/bin/bash")) - (should - (string-equal (symbol-value 'remote-shell-command-switch) "-c"))) - - ;; Everything is rewound. The old variable values are reset. - (should - (equal connection-local-variables-alist - (append - (nreverse (copy-tree files-x-test--variables3)) - (nreverse (copy-tree files-x-test--variables2))))) - ;; The variables exist also as local variables. - (should (local-variable-p 'remote-shell-file-name)) - (should (local-variable-p 'remote-null-device)) - ;; The proper variable values are set. The settings from - ;; `remote-ksh' are back. - (should - (string-equal (symbol-value 'remote-shell-file-name) "/bin/ksh")) - (should - (string-equal (symbol-value 'remote-null-device) "/dev/null")) + (should-not (local-variable-p 'remote-shell-command-switch)))) - ;; The variable set temporarily is not unbound, again. - (should-not (local-variable-p 'remote-shell-command-switch)))))) + (with-temp-buffer + ;; Use the macro. We need a remote `default-directory'. + (let ((enable-connection-local-variables t) + (default-directory "/method:host:") + (remote-null-device "null")) + (should-not connection-local-variables-alist) + (should-not (local-variable-p 'remote-shell-file-name)) + (should-not (local-variable-p 'remote-null-device)) + (should-not (boundp 'remote-shell-file-name)) + (should (string-equal (symbol-value 'remote-null-device) "null")) + + (with-connection-local-variables + ;; All connection-local variables are set. They apply in + ;; reverse order in `connection-local-variables-alist'. + ;; Since we ha a remote default directory, Tramp's settings + ;; are appended as well. + (should + (equal + connection-local-variables-alist + (append + (nreverse (copy-tree files-x-test--variables3)) + (nreverse (copy-tree files-x-test--variables2)) + (nreverse (copy-tree tramp-connection-local-default-profile))))) + ;; The variables exist also as local variables. + (should (local-variable-p 'remote-shell-file-name)) + (should (local-variable-p 'remote-null-device)) + ;; The proper variable values are set. + (should + (string-equal (symbol-value 'remote-shell-file-name) "/bin/ksh")) + (should + (string-equal (symbol-value 'remote-null-device) "/dev/null"))) + + ;; Everything is rewound. The old variable values are reset. + (should-not connection-local-variables-alist) + ;; The variables don't exist as local variables. + (should-not (local-variable-p 'remote-shell-file-name)) + (should-not (local-variable-p 'remote-null-device)) + ;; The variable values are reset. + (should-not (boundp 'remote-shell-file-name)) + (should (string-equal (symbol-value 'remote-null-device) "null")))))) (provide 'files-x-tests) ;;; files-x-tests.el ends here diff --git a/test/lisp/net/tramp-tests.el b/test/lisp/net/tramp-tests.el index 69d5ba8b7df..bf7cdfafabe 100644 --- a/test/lisp/net/tramp-tests.el +++ b/test/lisp/net/tramp-tests.el @@ -4274,12 +4274,78 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'." (dolist (dir '("/mock:localhost#11111:" "/mock:localhost#22222:")) (tramp-cleanup-connection (tramp-dissect-file-name dir))))) +;; Connection-local variables are enabled per default since Emacs 27.1. +(ert-deftest tramp-test34-connection-local-variables () + "Check that connection-local variables are enabled." + :tags '(:expensive-test) + (skip-unless (tramp--test-enabled)) + ;; Since Emacs 27.1. + (skip-unless (fboundp 'with-connection-local-variables)) + + ;; `connection-local-set-profile-variables' and + ;; `connection-local-set-profiles' exist since Emacs 26.1. We don't + ;; want to see compiler warnings for older Emacsen. + (let* ((default-directory tramp-test-temporary-file-directory) + (tmp-name1 (tramp--test-make-temp-name)) + (tmp-name2 (expand-file-name "foo" tmp-name1)) + (enable-local-variables :all) + (enable-remote-dir-locals t) + kill-buffer-query-functions + connection-local-profile-alist connection-local-criteria-alist) + (unwind-protect + (progn + (make-directory tmp-name1) + (should (file-directory-p tmp-name1)) + + ;; `local-variable' is buffer-local due to explicit setting. + (with-no-warnings + (defvar-local local-variable 'buffer)) + (with-temp-buffer + (should (eq local-variable 'buffer))) + + ;; `local-variable' is connection-local due to Tramp. + (write-region "foo" nil tmp-name2) + (should (file-exists-p tmp-name2)) + (with-no-warnings + (connection-local-set-profile-variables + 'local-variable-profile + '((local-variable . connect))) + (connection-local-set-profiles + `(:application tramp + :protocol ,(file-remote-p default-directory 'method) + :user ,(file-remote-p default-directory 'user) + :machine ,(file-remote-p default-directory 'host)) + 'local-variable-profile)) + (with-current-buffer (find-file-noselect tmp-name2) + (should (eq local-variable 'connect)) + (kill-buffer (current-buffer))) + + ;; `local-variable' is dir-local due to existence of .dir-locals.el. + (write-region + "((nil . ((local-variable . dir))))" nil + (expand-file-name ".dir-locals.el" tmp-name1)) + (should (file-exists-p (expand-file-name ".dir-locals.el" tmp-name1))) + (with-current-buffer (find-file-noselect tmp-name2) + (should (eq local-variable 'dir)) + (kill-buffer (current-buffer))) + + ;; `local-variable' is file-local due to specifying as file variable. + (write-region + "-*- mode: comint; local-variable: file; -*-" nil tmp-name2) + (should (file-exists-p tmp-name2)) + (with-current-buffer (find-file-noselect tmp-name2) + (should (eq local-variable 'file)) + (kill-buffer (current-buffer)))) + + ;; Cleanup. + (ignore-errors (delete-directory tmp-name1 'recursive))))) + ;; The functions were introduced in Emacs 26.1. (ert-deftest tramp-test34-explicit-shell-file-name () "Check that connection-local `explicit-shell-file-name' is set." :tags '(:expensive-test) (skip-unless (tramp--test-enabled)) - (skip-unless (tramp--test-sh-p)) + (skip-unless (or (tramp--test-adb-p) (tramp--test-sh-p))) ;; Since Emacs 26.1. (skip-unless (and (fboundp 'connection-local-set-profile-variables) (fboundp 'connection-local-set-profiles))) @@ -4288,7 +4354,8 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'." ;; `connection-local-set-profiles' exist since Emacs 26.1. We don't ;; want to see compiler warnings for older Emacsen. (let ((default-directory tramp-test-temporary-file-directory) - explicit-shell-file-name kill-buffer-query-functions) + explicit-shell-file-name kill-buffer-query-functions + connection-local-profile-alist connection-local-criteria-alist) (unwind-protect (progn ;; `shell-mode' would ruin our test, because it deletes all @@ -4298,7 +4365,8 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'." (with-no-warnings (connection-local-set-profile-variables 'remote-sh - '((explicit-shell-file-name . "/bin/sh") + `((explicit-shell-file-name + . ,(if (tramp--test-adb-p) "/system/bin/sh" "/bin/sh")) (explicit-sh-args . ("-i")))) (connection-local-set-profiles `(:application tramp @@ -4306,6 +4374,8 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'." :user ,(file-remote-p default-directory 'user) :machine ,(file-remote-p default-directory 'host)) 'remote-sh)) + (put 'explicit-shell-file-name 'safe-local-variable #'identity) + (put 'explicit-sh-args 'safe-local-variable #'identity) ;; Run interactive shell. Since the default directory is ;; remote, `explicit-shell-file-name' shall be set in order @@ -4316,6 +4386,7 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'." (call-interactively #'shell) (should explicit-shell-file-name))) + ;; Cleanup. (put 'explicit-shell-file-name 'permanent-local nil) (kill-buffer "*shell*")))) |