aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Albinus2019-03-09 16:44:24 +0100
committerMichael Albinus2019-03-09 16:44:24 +0100
commit21f54feee8c83e2c5fd8eeb6741cbd479a7b19eb (patch)
tree3edf223c49dfedf09ec93804856954a9554a93cd
parentc37bdd00c7dcabaa3ca8405d9dc5122ed36f27e0 (diff)
downloademacs-21f54feee8c83e2c5fd8eeb6741cbd479a7b19eb.tar.gz
emacs-21f54feee8c83e2c5fd8eeb6741cbd479a7b19eb.zip
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.texi48
-rw-r--r--doc/emacs/emacs.texi2
-rw-r--r--doc/emacs/misc.texi4
-rw-r--r--doc/lispref/variables.texi17
-rw-r--r--doc/misc/tramp.texi10
-rw-r--r--etc/NEWS16
-rw-r--r--lisp/files-x.el51
-rw-r--r--lisp/files.el5
-rw-r--r--lisp/net/ange-ftp.el4
-rw-r--r--lisp/net/tramp-adb.el20
-rw-r--r--lisp/net/tramp-integration.el34
-rw-r--r--lisp/net/tramp-sh.el1
-rw-r--r--lisp/progmodes/compile.el19
-rw-r--r--lisp/shell.el27
-rw-r--r--lisp/subr.el11
-rw-r--r--test/lisp/files-x-tests.el89
-rw-r--r--test/lisp/net/tramp-tests.el77
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}).
765* Locals:: Per-buffer values of variables. 765* Locals:: Per-buffer values of variables.
766* File Variables:: How files can specify variable values. 766* File Variables:: How files can specify variable values.
767* Directory Variables:: How variable values can be specified by directory. 767* Directory Variables:: How variable values can be specified by directory.
768* Connection Variables:: Variables which are valid for buffers with a
769 remote default directory.
768@end menu 770@end menu
769 771
770@node Examining 772@node Examining
@@ -1421,6 +1423,52 @@ variables are handled in the same way as unsafe file-local variables
1421do not visit a file directly but perform work within a directory, such 1423do not visit a file directly but perform work within a directory, such
1422as Dired buffers (@pxref{Dired}). 1424as Dired buffers (@pxref{Dired}).
1423 1425
1426@node Connection Variables
1427@subsection Per-Connection Local Variables
1428@cindex local variables, for all remote connections
1429@cindex connection-local variables
1430@cindex per-connection local variables
1431
1432 Most of the variables reflect the situation on the local machine.
1433Often, they must use a different value when you operate in buffers
1434with a remote default directory. Think about the shell to be applied
1435when calling @code{shell} -- it might be @file{/bin/bash} on your
1436local machine, and @file{/bin/ksh} on a remote machine.
1437
1438 This can be accomplished with @dfn{connection-local variables}.
1439Directory and file local variables override connection-local
1440variables. Unsafe connection-local variables are handled in the same
1441way as unsafe file-local variables (@pxref{Safe File Variables}).
1442
1443@findex connection-local-set-profile-variables
1444@findex connection-local-set-profiles
1445 Connection-local variables are declared as a group of
1446variables/value pairs in a @dfn{profile}, using the
1447@code{connection-local-set-profile-variables} function. The function
1448@code{connection-local-set-profiles} activates profiles for a given
1449criteria, identifying a remote machine:
1450
1451@example
1452(connection-local-set-profile-variables 'remote-ksh
1453 '((shell-file-name . "/bin/ksh")
1454 (shell-command-switch . "-c")))
1455
1456(connection-local-set-profile-variables 'remote-bash
1457 '((shell-file-name . "/bin/bash")
1458 (shell-command-switch . "-c")))
1459
1460(connection-local-set-profiles
1461 '(:application tramp :machine "remotemachine") 'remote-ksh)
1462@end example
1463
1464 This code declares two different profiles, @code{remote-ksh} and
1465@code{remote-bash}. The profile @code{remote-ksh} is applied to all
1466buffers which have a remote default directory matching the regexp
1467@code{"remotemachine} as host name. Such a criteria can also
1468discriminate for the properties @code{:protocol} (this is the Tramp
1469method) or @code{:user} (a remote user name). The @code{nil} criteria
1470matches all buffers with a remote default directory.
1471
1424@node Key Bindings 1472@node Key Bindings
1425@section Customizing Key Bindings 1473@section Customizing Key Bindings
1426@cindex key bindings 1474@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
1135* Locals:: Per-buffer values of variables. 1135* Locals:: Per-buffer values of variables.
1136* File Variables:: How files can specify variable values. 1136* File Variables:: How files can specify variable values.
1137* Directory Variables:: How variable values can be specified by directory. 1137* Directory Variables:: How variable values can be specified by directory.
1138* Connection Variables:: Variables which are valid for buffers with a
1139 remote default directory.
1138 1140
1139Local Variables in Files 1141Local Variables in Files
1140 1142
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
795name is relative, Emacs searches the directories listed in 795name is relative, Emacs searches the directories listed in
796@code{exec-path} (@pxref{Shell}). 796@code{exec-path} (@pxref{Shell}).
797 797
798 If the default directory is remote (@pxref{Remote Files}), the
799default value is @file{/bin/sh}. This can be changed by declaring
800@code{shell-file-name} connection-local (@pxref{Connection Variables}).
801
798 To specify a coding system for @kbd{M-!} or @kbd{M-|}, use the command 802 To specify a coding system for @kbd{M-!} or @kbd{M-|}, use the command
799@kbd{C-x @key{RET} c} immediately beforehand. @xref{Communication Coding}. 803@kbd{C-x @key{RET} c} immediately beforehand. @xref{Communication Coding}.
800 804
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
2191@var{criteria}, and immediately applies them in the current buffer. 2191@var{criteria}, and immediately applies them in the current buffer.
2192@end defun 2192@end defun
2193 2193
2194@defmac with-connection-local-profiles profiles &rest body 2194@defmac with-connection-local-variables &rest body
2195All connection-local variables, which are specified by a connection 2195All connection-local variables, which are specified by
2196profile in @var{profiles}, are applied. 2196@code{default-directory}, are applied.
2197 2197
2198After that, @var{body} is executed, and the connection-local variables 2198After that, @var{body} is executed, and the connection-local variables
2199are unwound. Example: 2199are unwound. Example:
@@ -2207,8 +2207,15 @@ are unwound. Example:
2207@end group 2207@end group
2208 2208
2209@group 2209@group
2210(with-connection-local-profiles '(remote-perl) 2210(connection-local-set-profiles
2211 do something useful) 2211 '(:application 'tramp :protocol "ssh" :machine "remotehost")
2212 'remote-perl)
2213@end group
2214
2215@group
2216(let ((default-directory "/ssh:remotehost:/working/dir/"))
2217 (with-connection-local-variables
2218 do something useful))
2212@end group 2219@end group
2213@end example 2220@end example
2214@end defmac 2221@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
2970setting different values of @code{explicit-shell-file-name} for 2970setting different values of @code{explicit-shell-file-name} for
2971different remote hosts. 2971different remote hosts.
2972@ifinfo 2972@ifinfo
2973@pxref{Connection Local Variables, , , elisp} 2973@xref{Connection Variables, , , emacs}
2974@end ifinfo 2974@end ifinfo
2975 2975
2976@lisp 2976@lisp
@@ -3023,6 +3023,14 @@ host. Example:
3023@kbd{M-x auto-revert-tail-mode @key{RET}} runs similarly showing 3023@kbd{M-x auto-revert-tail-mode @key{RET}} runs similarly showing
3024continuous output. 3024continuous output.
3025 3025
3026@code{shell-command} uses the variables @code{shell-file-name} and
3027@code{shell-command-switch} in order to determine which shell to run.
3028For remote hosts, their default values are @file{/bin/sh} and
3029@option{-c}, respectively (except for the @option{adb} method, which
3030uses @file{/system/bin/sh}). Like the variables in the previous
3031section, these variables can be changed via connection-local
3032variables.
3033
3026 3034
3027@subsection Running @code{eshell} on a remote host 3035@subsection Running @code{eshell} on a remote host
3028@cindex @code{eshell} 3036@cindex @code{eshell}
diff --git a/etc/NEWS b/etc/NEWS
index 1095ecc7e5e..0a1d9ea2220 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -279,6 +279,17 @@ matches strings where the pattern appears as a subsequence. Put
279simply, makes "foo" complete to both "barfoo" and "frodo". Add 'flex' 279simply, makes "foo" complete to both "barfoo" and "frodo". Add 'flex'
280to 'completion-styles' or 'completion-category-overrides' to use it. 280to 'completion-styles' or 'completion-category-overrides' to use it.
281 281
282** Connection-local variables
283
284+++
285*** Connection-local variables are applied by default like file-local
286and directory-local variables.
287
288+++
289*** The macro 'with-connection-local-variables' has been renamed from
290'with-connection-local-profiles'. No argument 'profiles' needed any
291longer.
292
282 293
283* Editing Changes in Emacs 27.1 294* Editing Changes in Emacs 27.1
284 295
@@ -994,7 +1005,12 @@ followed when Emacs writes the relevant history variables to the disk.
994--- 1005---
995*** Program name completion inside remote shells works now as expected. 1006*** Program name completion inside remote shells works now as expected.
996 1007
1008+++
1009*** The variable 'shell-file-name' can be set now as connection-local
1010variable for remote shells. It still defaults to "/bin/sh".
1011
997** Pcomplete 1012** Pcomplete
1013
998*** The function 'pcomplete-uniquify-list' has been renamed from 1014*** The function 'pcomplete-uniquify-list' has been renamed from
999'pcomplete-uniqify-list'. 1015'pcomplete-uniqify-list'.
1000 1016
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.")
582(setq ignored-local-variables 582(setq ignored-local-variables
583 (cons 'connection-local-variables-alist ignored-local-variables)) 583 (cons 'connection-local-variables-alist ignored-local-variables))
584 584
585(defvar connection-local-profile-alist '() 585(defvar connection-local-profile-alist nil
586 "Alist mapping connection profiles to variable lists. 586 "Alist mapping connection profiles to variable lists.
587Each element in this list has the form (PROFILE VARIABLES). 587Each element in this list has the form (PROFILE VARIABLES).
588PROFILE is the name of a connection profile (a symbol). 588PROFILE is the name of a connection profile (a symbol).
@@ -590,7 +590,7 @@ VARIABLES is a list that declares connection-local variables for
590PROFILE. An element in VARIABLES is an alist whose elements are 590PROFILE. An element in VARIABLES is an alist whose elements are
591of the form (VAR . VALUE).") 591of the form (VAR . VALUE).")
592 592
593(defvar connection-local-criteria-alist '() 593(defvar connection-local-criteria-alist nil
594 "Alist mapping connection criteria to connection profiles. 594 "Alist mapping connection criteria to connection profiles.
595Each element in this list has the form (CRITERIA PROFILES). 595Each element in this list has the form (CRITERIA PROFILES).
596CRITERIA is a plist identifying a connection and the application 596CRITERIA is a plist identifying a connection and the application
@@ -685,7 +685,9 @@ This does nothing if `enable-connection-local-variables' is nil."
685 ;; Loop over variables. 685 ;; Loop over variables.
686 (dolist (variable (connection-local-get-profile-variables profile)) 686 (dolist (variable (connection-local-get-profile-variables profile))
687 (unless (assq (car variable) connection-local-variables-alist) 687 (unless (assq (car variable) connection-local-variables-alist)
688 (push variable connection-local-variables-alist)))))) 688 (push variable connection-local-variables-alist))))
689 ;; Push them to `file-local-variables-alist'.
690 (hack-local-variables-filter connection-local-variables-alist nil)))
689 691
690;;;###autoload 692;;;###autoload
691(defun hack-connection-local-variables-apply (criteria) 693(defun hack-connection-local-variables-apply (criteria)
@@ -697,24 +699,35 @@ will not be changed."
697 (copy-tree connection-local-variables-alist))) 699 (copy-tree connection-local-variables-alist)))
698 (hack-local-variables-apply))) 700 (hack-local-variables-apply)))
699 701
702(defsubst connection-local-criteria-for-default-directory ()
703 "Return a connection-local criteria, which represents `default-directory'."
704 (when (file-remote-p default-directory)
705 `(:application tramp
706 :protocol ,(file-remote-p default-directory 'method)
707 :user ,(file-remote-p default-directory 'user)
708 :machine ,(file-remote-p default-directory 'host))))
709
700;;;###autoload 710;;;###autoload
701(defmacro with-connection-local-profiles (profiles &rest body) 711(defmacro with-connection-local-variables (&rest body)
702 "Apply connection-local variables according to PROFILES in current buffer. 712 "Apply connection-local variables according to `default-directory'.
703Execute BODY, and unwind connection-local variables." 713Execute BODY, and unwind connection-local variables."
704 (declare (indent 1) (debug t)) 714 (declare (debug t))
705 `(let ((enable-connection-local-variables t) 715 `(if (file-remote-p default-directory)
706 (old-buffer-local-variables (buffer-local-variables)) 716 (let ((enable-connection-local-variables t)
707 connection-local-variables-alist connection-local-criteria-alist) 717 (old-buffer-local-variables (buffer-local-variables))
708 (apply 'connection-local-set-profiles nil ,profiles) 718 connection-local-variables-alist)
709 (hack-connection-local-variables-apply nil) 719 (hack-connection-local-variables-apply
710 (unwind-protect 720 (connection-local-criteria-for-default-directory))
711 (progn ,@body) 721 (unwind-protect
712 ;; Cleanup. 722 (progn ,@body)
713 (dolist (variable connection-local-variables-alist) 723 ;; Cleanup.
714 (let ((elt (assq (car variable) old-buffer-local-variables))) 724 (dolist (variable connection-local-variables-alist)
715 (if elt 725 (let ((elt (assq (car variable) old-buffer-local-variables)))
716 (set (make-local-variable (car elt)) (cdr elt)) 726 (if elt
717 (kill-local-variable (car variable)))))))) 727 (set (make-local-variable (car elt)) (cdr elt))
728 (kill-local-variable (car variable)))))))
729 ;; No connection-local variables to apply.
730 ,@body))
718 731
719 732
720 733
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."
3590 result) 3590 result)
3591 (unless (eq handle-mode t) 3591 (unless (eq handle-mode t)
3592 (setq file-local-variables-alist nil) 3592 (setq file-local-variables-alist nil)
3593 (when (file-remote-p default-directory)
3594 (with-demoted-errors "Connection-local variables error: %s"
3595 ;; Note this is a no-op if enable-local-variables is nil.
3596 (hack-connection-local-variables
3597 (connection-local-criteria-for-default-directory))))
3593 (with-demoted-errors "Directory-local variables error: %s" 3598 (with-demoted-errors "Directory-local variables error: %s"
3594 ;; Note this is a no-op if enable-local-variables is nil. 3599 ;; Note this is a no-op if enable-local-variables is nil.
3595 (hack-dir-local-variables))) 3600 (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.")
4277 nil 4277 nil
4278 t 4278 t
4279 nil 4279 nil
4280 "-c" 4280 shell-command-switch
4281 (format "compress -f -c < %s > %s" tmp1 tmp2)) 4281 (format "compress -f -c < %s > %s" tmp1 tmp2))
4282 (and ange-ftp-process-verbose 4282 (and ange-ftp-process-verbose
4283 (ange-ftp-message "Compressing %s...done" abbr)) 4283 (ange-ftp-message "Compressing %s...done" abbr))
@@ -4313,7 +4313,7 @@ NEWNAME should be the name to give the new compressed or uncompressed file.")
4313 nil 4313 nil
4314 t 4314 t
4315 nil 4315 nil
4316 "-c" 4316 shell-command-switch
4317 (format "uncompress -c < %s > %s" tmp1 tmp2)) 4317 (format "uncompress -c < %s > %s" tmp1 tmp2))
4318 (and ange-ftp-process-verbose 4318 (and ange-ftp-process-verbose
4319 (ange-ftp-message "Uncompressing %s...done" abbr)) 4319 (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."
1370 ;; Mark it as connected. 1370 ;; Mark it as connected.
1371 (tramp-set-connection-property p "connected" t))))))) 1371 (tramp-set-connection-property p "connected" t)))))))
1372 1372
1373;; Default settings for connection-local variables.
1374(defconst tramp-adb-connection-local-default-profile
1375 '((shell-file-name . "/system/bin/sh")
1376 (shell-command-switch . "-c"))
1377 "Default connection-local variables for remote adb connections.")
1378(add-to-list 'tramp-connection-local-safe-shell-file-names "/system/bin/sh")
1379
1380;; `connection-local-set-profile-variables' and
1381;; `connection-local-set-profiles' exists since Emacs 26.1.
1382(eval-after-load "shell"
1383 '(progn
1384 (tramp-compat-funcall
1385 'connection-local-set-profile-variables
1386 'tramp-adb-connection-local-default-profile
1387 tramp-adb-connection-local-default-profile)
1388 (tramp-compat-funcall
1389 'connection-local-set-profiles
1390 `(:application tramp :protocol ,tramp-adb-method)
1391 'tramp-adb-connection-local-default-profile)))
1392
1373(add-hook 'tramp-unload-hook 1393(add-hook 'tramp-unload-hook
1374 (lambda () 1394 (lambda ()
1375 (unload-feature 'tramp-adb 'force))) 1395 (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 @@
27 27
28;;; Code: 28;;; Code:
29 29
30(require 'tramp-compat)
31
30;; Pacify byte-compiler. 32;; Pacify byte-compiler.
31(require 'cl-lib) 33(require 'cl-lib)
32(declare-function tramp-compat-exec-path "tramp")
33(declare-function tramp-dissect-file-name "tramp") 34(declare-function tramp-dissect-file-name "tramp")
34(declare-function tramp-file-name-equal-p "tramp") 35(declare-function tramp-file-name-equal-p "tramp")
35(declare-function tramp-tramp-file-p "tramp") 36(declare-function tramp-tramp-file-p "tramp")
@@ -170,6 +171,37 @@ NAME must be equal to `tramp-current-connection'."
170 (remove-hook 'tramp-cleanup-all-connections-hook 171 (remove-hook 'tramp-cleanup-all-connections-hook
171 #'tramp-recentf-cleanup-all))))) 172 #'tramp-recentf-cleanup-all)))))
172 173
174;;; Default connection-local variables for Tramp:
175
176;;;###tramp-autoload
177(defvar tramp-connection-local-safe-shell-file-names nil
178 "List of safe `shell-file-name' values for remote hosts.")
179(add-to-list 'tramp-connection-local-safe-shell-file-names "/bin/sh")
180
181(defconst tramp-connection-local-default-profile
182 '((shell-file-name . "/bin/sh")
183 (shell-command-switch . "-c"))
184 "Default connection-local variables for remote connections.")
185(put 'shell-file-name 'safe-local-variable
186 (lambda (item)
187 (and (stringp item)
188 (member item tramp-connection-local-safe-shell-file-names))))
189(put 'shell-command-switch 'safe-local-variable
190 (lambda (item) (and (stringp item) (string-equal item "-c"))))
191
192;; `connection-local-set-profile-variables' and
193;; `connection-local-set-profiles' exists since Emacs 26.1.
194(eval-after-load "shell"
195 '(progn
196 (tramp-compat-funcall
197 'connection-local-set-profile-variables
198 'tramp-connection-local-default-profile
199 tramp-connection-local-default-profile)
200 (tramp-compat-funcall
201 'connection-local-set-profiles
202 `(:application tramp)
203 'tramp-connection-local-default-profile)))
204
173(add-hook 'tramp-unload-hook 205(add-hook 'tramp-unload-hook
174 (lambda () (unload-feature 'tramp-integration 'force))) 206 (lambda () (unload-feature 'tramp-integration 'force)))
175 207
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\"."
81 (const :tag "Unset HISTFILE" t) 81 (const :tag "Unset HISTFILE" t)
82 (string :tag "Redirect to a file"))) 82 (string :tag "Redirect to a file")))
83 83
84;;;###tramp-autoload
84(defconst tramp-display-escape-sequence-regexp "\e[[;0-9]+m" 85(defconst tramp-display-escape-sequence-regexp "\e[[;0-9]+m"
85 "Terminal control escape sequences for display attributes.") 86 "Terminal control escape sequences for display attributes.")
86 87
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."
1754 (if (fboundp 'make-process) 1754 (if (fboundp 'make-process)
1755 (let ((proc 1755 (let ((proc
1756 (if (eq mode t) 1756 (if (eq mode t)
1757 ;; comint uses `start-file-process'. 1757 ;; On remote hosts, the local `shell-file-name'
1758 (get-buffer-process 1758 ;; might be useless.
1759 (with-no-warnings 1759 (with-connection-local-variables
1760 (comint-exec 1760 ;; comint uses `start-file-process'.
1761 outbuf (downcase mode-name) 1761 (get-buffer-process
1762 (if (file-remote-p default-directory) 1762 (with-no-warnings
1763 "/bin/sh" 1763 (comint-exec
1764 shell-file-name) 1764 outbuf (downcase mode-name)
1765 nil `("-c" ,command)))) 1765 shell-file-name
1766 nil `(,shell-command-switch ,command)))))
1766 (start-file-process-shell-command (downcase mode-name) 1767 (start-file-process-shell-command (downcase mode-name)
1767 outbuf command)))) 1768 outbuf command))))
1768 ;; Make the buffer's mode line show process state. 1769 ;; 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 @@
99 99
100(require 'comint) 100(require 'comint)
101(require 'pcomplete) 101(require 'pcomplete)
102(eval-when-compile (require 'files-x)) ;with-connection-local-variables
102 103
103;;; Customization and Buffer Variables 104;;; Customization and Buffer Variables
104 105
@@ -721,23 +722,17 @@ Otherwise, one argument `-i' is passed to the shell.
721 722
722 (with-current-buffer buffer 723 (with-current-buffer buffer
723 (when (file-remote-p default-directory) 724 (when (file-remote-p default-directory)
724 ;; Apply connection-local variables.
725 (hack-connection-local-variables-apply
726 `(:application tramp
727 :protocol ,(file-remote-p default-directory 'method)
728 :user ,(file-remote-p default-directory 'user)
729 :machine ,(file-remote-p default-directory 'host)))
730
731 ;; On remote hosts, the local `shell-file-name' might be useless. 725 ;; On remote hosts, the local `shell-file-name' might be useless.
732 (if (and (called-interactively-p 'any) 726 (with-connection-local-variables
733 (null explicit-shell-file-name) 727 (if (and (called-interactively-p 'any)
734 (null (getenv "ESHELL"))) 728 (null explicit-shell-file-name)
735 (set (make-local-variable 'explicit-shell-file-name) 729 (null (getenv "ESHELL")))
736 (file-local-name 730 (set (make-local-variable 'explicit-shell-file-name)
737 (expand-file-name 731 (file-local-name
738 (read-file-name 732 (expand-file-name
739 "Remote shell path: " default-directory shell-file-name 733 (read-file-name
740 t shell-file-name))))))) 734 "Remote shell path: " default-directory shell-file-name
735 t shell-file-name))))))))
741 736
742 ;; The buffer's window must be correctly set when we call comint 737 ;; The buffer's window must be correctly set when we call comint
743 ;; (so that comint sets the COLUMNS env var properly). 738 ;; (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."
3185 "Start a program in a subprocess. Return the process object for it. 3185 "Start a program in a subprocess. Return the process object for it.
3186Similar to `start-process-shell-command', but calls `start-file-process'." 3186Similar to `start-process-shell-command', but calls `start-file-process'."
3187 (declare (advertised-calling-convention (name buffer command) "23.1")) 3187 (declare (advertised-calling-convention (name buffer command) "23.1"))
3188 (start-file-process 3188 ;; On remote hosts, the local `shell-file-name' might be useless.
3189 name buffer 3189 (with-connection-local-variables
3190 (if (file-remote-p default-directory) "/bin/sh" shell-file-name) 3190 (start-file-process
3191 (if (file-remote-p default-directory) "-c" shell-command-switch) 3191 name buffer
3192 (mapconcat 'identity args " "))) 3192 shell-file-name shell-command-switch
3193 (mapconcat 'identity args " "))))
3193 3194
3194(defun call-process-shell-command (command &optional infile buffer display 3195(defun call-process-shell-command (command &optional infile buffer display
3195 &rest args) 3196 &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 @@
35 '((remote-null-device . "/dev/null"))) 35 '((remote-null-device . "/dev/null")))
36(defconst files-x-test--variables4 36(defconst files-x-test--variables4
37 '((remote-null-device . "null"))) 37 '((remote-null-device . "null")))
38(put 'remote-shell-file-name 'safe-local-variable #'identity)
39(put 'remote-shell-command-switch 'safe-local-variable #'identity)
40(put 'remote-shell-interactive-switch 'safe-local-variable #'identity)
41(put 'remote-shell-login-switch 'safe-local-variable #'identity)
42(put 'remote-null-device 'safe-local-variable #'identity)
38 43
39(defconst files-x-test--application '(:application 'my-application)) 44(defconst files-x-test--application '(:application 'my-application))
40(defconst files-x-test--another-application 45(defconst files-x-test--another-application
@@ -268,7 +273,9 @@
268 (should-not (local-variable-p 'remote-shell-file-name)) 273 (should-not (local-variable-p 'remote-shell-file-name))
269 (should-not (boundp 'remote-shell-file-name)))))) 274 (should-not (boundp 'remote-shell-file-name))))))
270 275
271(ert-deftest files-x-test-with-connection-local-profiles () 276(defvar tramp-connection-local-default-profile)
277
278(ert-deftest files-x-test-with-connection-local-variables ()
272 "Test setting connection-local variables." 279 "Test setting connection-local variables."
273 280
274 (let (connection-local-profile-alist connection-local-criteria-alist) 281 (let (connection-local-profile-alist connection-local-criteria-alist)
@@ -303,46 +310,48 @@
303 (string-equal (symbol-value 'remote-null-device) "/dev/null")) 310 (string-equal (symbol-value 'remote-null-device) "/dev/null"))
304 311
305 ;; A candidate connection-local variable is not bound yet. 312 ;; A candidate connection-local variable is not bound yet.
306 (should-not (local-variable-p 'remote-shell-command-switch)) 313 (should-not (local-variable-p 'remote-shell-command-switch))))
307
308 ;; Use the macro.
309 (with-connection-local-profiles '(remote-bash remote-ksh)
310 ;; All connection-local variables are set. They apply in
311 ;; reverse order in `connection-local-variables-alist'.
312 ;; This variable keeps only the variables to be set inside
313 ;; the macro.
314 (should
315 (equal connection-local-variables-alist
316 (nreverse (copy-tree files-x-test--variables1))))
317 ;; The variables exist also as local variables.
318 (should (local-variable-p 'remote-shell-file-name))
319 (should (local-variable-p 'remote-shell-command-switch))
320 ;; The proper variable values are set. The settings from
321 ;; `remote-bash' overwrite the same variables as in
322 ;; `remote-ksh'.
323 (should
324 (string-equal (symbol-value 'remote-shell-file-name) "/bin/bash"))
325 (should
326 (string-equal (symbol-value 'remote-shell-command-switch) "-c")))
327
328 ;; Everything is rewound. The old variable values are reset.
329 (should
330 (equal connection-local-variables-alist
331 (append
332 (nreverse (copy-tree files-x-test--variables3))
333 (nreverse (copy-tree files-x-test--variables2)))))
334 ;; The variables exist also as local variables.
335 (should (local-variable-p 'remote-shell-file-name))
336 (should (local-variable-p 'remote-null-device))
337 ;; The proper variable values are set. The settings from
338 ;; `remote-ksh' are back.
339 (should
340 (string-equal (symbol-value 'remote-shell-file-name) "/bin/ksh"))
341 (should
342 (string-equal (symbol-value 'remote-null-device) "/dev/null"))
343 314
344 ;; The variable set temporarily is not unbound, again. 315 (with-temp-buffer
345 (should-not (local-variable-p 'remote-shell-command-switch)))))) 316 ;; Use the macro. We need a remote `default-directory'.
317 (let ((enable-connection-local-variables t)
318 (default-directory "/method:host:")
319 (remote-null-device "null"))
320 (should-not connection-local-variables-alist)
321 (should-not (local-variable-p 'remote-shell-file-name))
322 (should-not (local-variable-p 'remote-null-device))
323 (should-not (boundp 'remote-shell-file-name))
324 (should (string-equal (symbol-value 'remote-null-device) "null"))
325
326 (with-connection-local-variables
327 ;; All connection-local variables are set. They apply in
328 ;; reverse order in `connection-local-variables-alist'.
329 ;; Since we ha a remote default directory, Tramp's settings
330 ;; are appended as well.
331 (should
332 (equal
333 connection-local-variables-alist
334 (append
335 (nreverse (copy-tree files-x-test--variables3))
336 (nreverse (copy-tree files-x-test--variables2))
337 (nreverse (copy-tree tramp-connection-local-default-profile)))))
338 ;; The variables exist also as local variables.
339 (should (local-variable-p 'remote-shell-file-name))
340 (should (local-variable-p 'remote-null-device))
341 ;; The proper variable values are set.
342 (should
343 (string-equal (symbol-value 'remote-shell-file-name) "/bin/ksh"))
344 (should
345 (string-equal (symbol-value 'remote-null-device) "/dev/null")))
346
347 ;; Everything is rewound. The old variable values are reset.
348 (should-not connection-local-variables-alist)
349 ;; The variables don't exist as local variables.
350 (should-not (local-variable-p 'remote-shell-file-name))
351 (should-not (local-variable-p 'remote-null-device))
352 ;; The variable values are reset.
353 (should-not (boundp 'remote-shell-file-name))
354 (should (string-equal (symbol-value 'remote-null-device) "null"))))))
346 355
347(provide 'files-x-tests) 356(provide 'files-x-tests)
348;;; files-x-tests.el ends here 357;;; 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'."
4274 (dolist (dir '("/mock:localhost#11111:" "/mock:localhost#22222:")) 4274 (dolist (dir '("/mock:localhost#11111:" "/mock:localhost#22222:"))
4275 (tramp-cleanup-connection (tramp-dissect-file-name dir))))) 4275 (tramp-cleanup-connection (tramp-dissect-file-name dir)))))
4276 4276
4277;; Connection-local variables are enabled per default since Emacs 27.1.
4278(ert-deftest tramp-test34-connection-local-variables ()
4279 "Check that connection-local variables are enabled."
4280 :tags '(:expensive-test)
4281 (skip-unless (tramp--test-enabled))
4282 ;; Since Emacs 27.1.
4283 (skip-unless (fboundp 'with-connection-local-variables))
4284
4285 ;; `connection-local-set-profile-variables' and
4286 ;; `connection-local-set-profiles' exist since Emacs 26.1. We don't
4287 ;; want to see compiler warnings for older Emacsen.
4288 (let* ((default-directory tramp-test-temporary-file-directory)
4289 (tmp-name1 (tramp--test-make-temp-name))
4290 (tmp-name2 (expand-file-name "foo" tmp-name1))
4291 (enable-local-variables :all)
4292 (enable-remote-dir-locals t)
4293 kill-buffer-query-functions
4294 connection-local-profile-alist connection-local-criteria-alist)
4295 (unwind-protect
4296 (progn
4297 (make-directory tmp-name1)
4298 (should (file-directory-p tmp-name1))
4299
4300 ;; `local-variable' is buffer-local due to explicit setting.
4301 (with-no-warnings
4302 (defvar-local local-variable 'buffer))
4303 (with-temp-buffer
4304 (should (eq local-variable 'buffer)))
4305
4306 ;; `local-variable' is connection-local due to Tramp.
4307 (write-region "foo" nil tmp-name2)
4308 (should (file-exists-p tmp-name2))
4309 (with-no-warnings
4310 (connection-local-set-profile-variables
4311 'local-variable-profile
4312 '((local-variable . connect)))
4313 (connection-local-set-profiles
4314 `(:application tramp
4315 :protocol ,(file-remote-p default-directory 'method)
4316 :user ,(file-remote-p default-directory 'user)
4317 :machine ,(file-remote-p default-directory 'host))
4318 'local-variable-profile))
4319 (with-current-buffer (find-file-noselect tmp-name2)
4320 (should (eq local-variable 'connect))
4321 (kill-buffer (current-buffer)))
4322
4323 ;; `local-variable' is dir-local due to existence of .dir-locals.el.
4324 (write-region
4325 "((nil . ((local-variable . dir))))" nil
4326 (expand-file-name ".dir-locals.el" tmp-name1))
4327 (should (file-exists-p (expand-file-name ".dir-locals.el" tmp-name1)))
4328 (with-current-buffer (find-file-noselect tmp-name2)
4329 (should (eq local-variable 'dir))
4330 (kill-buffer (current-buffer)))
4331
4332 ;; `local-variable' is file-local due to specifying as file variable.
4333 (write-region
4334 "-*- mode: comint; local-variable: file; -*-" nil tmp-name2)
4335 (should (file-exists-p tmp-name2))
4336 (with-current-buffer (find-file-noselect tmp-name2)
4337 (should (eq local-variable 'file))
4338 (kill-buffer (current-buffer))))
4339
4340 ;; Cleanup.
4341 (ignore-errors (delete-directory tmp-name1 'recursive)))))
4342
4277;; The functions were introduced in Emacs 26.1. 4343;; The functions were introduced in Emacs 26.1.
4278(ert-deftest tramp-test34-explicit-shell-file-name () 4344(ert-deftest tramp-test34-explicit-shell-file-name ()
4279 "Check that connection-local `explicit-shell-file-name' is set." 4345 "Check that connection-local `explicit-shell-file-name' is set."
4280 :tags '(:expensive-test) 4346 :tags '(:expensive-test)
4281 (skip-unless (tramp--test-enabled)) 4347 (skip-unless (tramp--test-enabled))
4282 (skip-unless (tramp--test-sh-p)) 4348 (skip-unless (or (tramp--test-adb-p) (tramp--test-sh-p)))
4283 ;; Since Emacs 26.1. 4349 ;; Since Emacs 26.1.
4284 (skip-unless (and (fboundp 'connection-local-set-profile-variables) 4350 (skip-unless (and (fboundp 'connection-local-set-profile-variables)
4285 (fboundp 'connection-local-set-profiles))) 4351 (fboundp 'connection-local-set-profiles)))
@@ -4288,7 +4354,8 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
4288 ;; `connection-local-set-profiles' exist since Emacs 26.1. We don't 4354 ;; `connection-local-set-profiles' exist since Emacs 26.1. We don't
4289 ;; want to see compiler warnings for older Emacsen. 4355 ;; want to see compiler warnings for older Emacsen.
4290 (let ((default-directory tramp-test-temporary-file-directory) 4356 (let ((default-directory tramp-test-temporary-file-directory)
4291 explicit-shell-file-name kill-buffer-query-functions) 4357 explicit-shell-file-name kill-buffer-query-functions
4358 connection-local-profile-alist connection-local-criteria-alist)
4292 (unwind-protect 4359 (unwind-protect
4293 (progn 4360 (progn
4294 ;; `shell-mode' would ruin our test, because it deletes all 4361 ;; `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'."
4298 (with-no-warnings 4365 (with-no-warnings
4299 (connection-local-set-profile-variables 4366 (connection-local-set-profile-variables
4300 'remote-sh 4367 'remote-sh
4301 '((explicit-shell-file-name . "/bin/sh") 4368 `((explicit-shell-file-name
4369 . ,(if (tramp--test-adb-p) "/system/bin/sh" "/bin/sh"))
4302 (explicit-sh-args . ("-i")))) 4370 (explicit-sh-args . ("-i"))))
4303 (connection-local-set-profiles 4371 (connection-local-set-profiles
4304 `(:application tramp 4372 `(:application tramp
@@ -4306,6 +4374,8 @@ This tests also `make-symbolic-link', `file-truename' and `add-name-to-file'."
4306 :user ,(file-remote-p default-directory 'user) 4374 :user ,(file-remote-p default-directory 'user)
4307 :machine ,(file-remote-p default-directory 'host)) 4375 :machine ,(file-remote-p default-directory 'host))
4308 'remote-sh)) 4376 'remote-sh))
4377 (put 'explicit-shell-file-name 'safe-local-variable #'identity)
4378 (put 'explicit-sh-args 'safe-local-variable #'identity)
4309 4379
4310 ;; Run interactive shell. Since the default directory is 4380 ;; Run interactive shell. Since the default directory is
4311 ;; remote, `explicit-shell-file-name' shall be set in order 4381 ;; 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'."
4316 (call-interactively #'shell) 4386 (call-interactively #'shell)
4317 (should explicit-shell-file-name))) 4387 (should explicit-shell-file-name)))
4318 4388
4389 ;; Cleanup.
4319 (put 'explicit-shell-file-name 'permanent-local nil) 4390 (put 'explicit-shell-file-name 'permanent-local nil)
4320 (kill-buffer "*shell*")))) 4391 (kill-buffer "*shell*"))))
4321 4392