aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Albinus2016-11-14 13:56:58 +0100
committerMichael Albinus2016-11-14 13:56:58 +0100
commit6647e05174ade1132a957e7e27f9ef6e96f3f9d7 (patch)
treedc94c02f1da132fcdd15af167da56605b172d808
parentdb43613307bb05d0f43d2d5649b5bb2f29876cee (diff)
downloademacs-6647e05174ade1132a957e7e27f9ef6e96f3f9d7.tar.gz
emacs-6647e05174ade1132a957e7e27f9ef6e96f3f9d7.zip
Implement connection-local variables
* doc/lispref/variables.texi (Connection Local Variables): New section. * etc/NEWS: Mention connection-local variables. * lisp/files-x.el (enable-connection-local-variables) (connection-local-variables-alist, connection-local-class-alist) (connection-local-criteria-alist): New defvars. (connection-local-get-classes) (connection-local-get-class-variables): New defsubst. (connection-local-set-classes) (connection-local-set-class-variables) (hack-connection-local-variables) (hack-connection-local-variables-apply): New defuns. (with-connection-local-classes): New defmacro. * lisp/net/tramp.el (tramp-set-connection-local-variables): New defun. * lisp/net/tramp-adb.el (tramp-adb-maybe-open-connection): * lisp/net/tramp-gvfs.el (tramp-gvfs-maybe-open-connection): * lisp/net/lisp/net/tramp-sh.el (tramp-maybe-open-connection): * lisp/net/tramp-smb.el (tramp-smb-maybe-open-connection): Use it. * test/lisp/files-x-tests.el: New file.
-rw-r--r--doc/lispref/variables.texi165
-rw-r--r--etc/NEWS5
-rw-r--r--lisp/files-x.el139
-rw-r--r--lisp/net/tramp-adb.el3
-rw-r--r--lisp/net/tramp-gvfs.el3
-rw-r--r--lisp/net/tramp-gw.el2
-rw-r--r--lisp/net/tramp-sh.el4
-rw-r--r--lisp/net/tramp-smb.el3
-rw-r--r--lisp/net/tramp.el16
-rw-r--r--test/lisp/files-x-tests.el297
10 files changed, 630 insertions, 7 deletions
diff --git a/doc/lispref/variables.texi b/doc/lispref/variables.texi
index 418a4161a7a..8a177973e11 100644
--- a/doc/lispref/variables.texi
+++ b/doc/lispref/variables.texi
@@ -38,6 +38,7 @@ representing the variable.
38* Buffer-Local Variables:: Variable values in effect only in one buffer. 38* Buffer-Local Variables:: Variable values in effect only in one buffer.
39* File Local Variables:: Handling local variable lists in files. 39* File Local Variables:: Handling local variable lists in files.
40* Directory Local Variables:: Local variables common to all files in a directory. 40* Directory Local Variables:: Local variables common to all files in a directory.
41* Connection Local Variables:: Local variables common for remote connections.
41* Variable Aliases:: Variables that are aliases for other variables. 42* Variable Aliases:: Variables that are aliases for other variables.
42* Variables with Restricted Values:: Non-constant variables whose value can 43* Variables with Restricted Values:: Non-constant variables whose value can
43 @emph{not} be an arbitrary Lisp object. 44 @emph{not} be an arbitrary Lisp object.
@@ -1862,6 +1863,170 @@ may be useful for modes that want to ignore directory-locals while
1862still respecting file-local variables (@pxref{File Local Variables}). 1863still respecting file-local variables (@pxref{File Local Variables}).
1863@end defvar 1864@end defvar
1864 1865
1866@node Connection Local Variables
1867@section Connection Local Variables
1868@cindex connection local variables
1869
1870 Connection-local variables provide a general mechanism for
1871different variable settings in buffers with a remote default
1872directory. They are bound and set depending on the remote connection
1873a buffer is dedicated to. Per default, they are set in all process
1874buffers for a remote connection, but they could be applied also in
1875other buffers with a remote directory.
1876
1877@defun connection-local-set-class-variables class variables
1878This function defines a set of variable settings for the named
1879@var{class}, which is a symbol. You can later assign the class to one
1880or more remote connections, and Emacs will apply those variable
1881settings to all process buffers for those connections. The list in
1882@var{variables} is an alist of the form @code{(@var{name}
1883. @var{value})}. Example:
1884
1885@example
1886@group
1887(connection-local-set-class-variables
1888 'remote-bash
1889 '((shell-file-name . "/bin/bash")
1890 (shell-command-switch . "-c")
1891 (shell-interactive-switch . "-i")
1892 (shell-login-switch . "-l")))
1893@end group
1894
1895@group
1896(connection-local-set-class-variables
1897 'remote-ksh
1898 '((shell-file-name . "/bin/ksh")
1899 (shell-command-switch . "-c")
1900 (shell-interactive-switch . "-i")
1901 (shell-login-switch . "-l")))
1902@end group
1903
1904@group
1905(connection-local-set-class-variables
1906 'remote-null-device
1907 '((null-device "/dev/null")))
1908@end group
1909@end example
1910@end defun
1911
1912@defvar connection-local-class-alist
1913This alist holds the class symbols and the associated variable
1914settings. It is updated by @code{connection-local-set-class-variables}.
1915@end defvar
1916
1917@defun connection-local-set-classes criteria &rest classes
1918This function assigns @var{classes}, which are symbols, to all remote
1919connections identified by @var{criteria}. @var{criteria} is either a
1920regular expression identifying a remote server, or a function with one
1921argument @var{identification}, which must return non-nil when a remote
1922server shall apply @var{classes} variables, or @code{nil}.
1923
1924If @var{criteria} is a regexp, is must match the result of
1925@code{(file-remote-p default-directory)} of a buffer in order to apply
1926the variables setting. Example:
1927
1928@example
1929@group
1930(connection-local-set-classes
1931 "^/ssh:" 'remote-bash 'remote-null-device)
1932@end group
1933
1934@group
1935(connection-local-set-classes
1936 "^/sudo:" 'remote-ksh 'remote-null-device)
1937@end group
1938@end example
1939
1940 If @var{criteria} is nil, it applies for all remote connections.
1941Therefore, the example above would be equivalent to
1942
1943@example
1944(connection-local-set-classes "^/ssh:" 'remote-bash)
1945(connection-local-set-classes "^/sudo:" 'remote-ksh)
1946(connection-local-set-classes nil 'remote-null-device)
1947@end example
1948
1949 If @var{criteria} is a lambda function it must accept one parameter,
1950the identification. The example above could be rewritten as
1951
1952@example
1953@group
1954(connection-local-set-classes
1955 (lambda (identification)
1956 (string-equal (file-remote-p identification 'method) "ssh"))
1957 'remote-bash)
1958@end group
1959
1960@group
1961(connection-local-set-classes
1962 (lambda (identification)
1963 (string-equal (file-remote-p identification 'method) "sudo"))
1964 'remote-ksh)
1965@end group
1966
1967@group
1968(connection-local-set-classes
1969 (lambda (identification) t)
1970 'remote-null-device)
1971@end group
1972@end example
1973
1974 Thereafter, all the variable settings specified for @var{classes}
1975will be applied to any buffer with a matching remote directory, when
1976activated by @code{hack-connection-local-variables-apply}. Any class
1977of @var{classes} must have been already defined by
1978@code{connection-local-set-class-variables}.
1979@end defun
1980
1981@defvar connection-local-criteria-alist
1982This alist contains remote server identifications and their assigned
1983class names. The function @code{connection-local-set-classes} updates
1984this list.
1985@end defvar
1986
1987@defun hack-connection-local-variables
1988This function collects applicable connection-local variables in
1989@code{connection-local-variables-alist} that is local to the buffer,
1990without applying them. Whether a connection-local variable is
1991applicable is specified by the remote identifier of a buffer,
1992evaluated by @code{(file-remote-p default-directory)}.
1993@end defun
1994
1995@defun hack-connection-local-variables-apply
1996This function looks for connection-local variables, and immediately
1997applies them in the current buffer. It is called per default for
1998every process-buffer related to a remote connection. For other remote
1999buffers, it could be called by any mode.
2000@end defun
2001
2002@defmac with-connection-local-classes classes &rest body
2003All connection-local variables, which are specified by a class in
2004@var{CLASSES}, are applied. An implicit binding of the classes to the
2005remote connection is enabled.
2006
2007After that, @var{BODY} is executed, and the connection-local variables
2008are unwound. Example:
2009
2010@example
2011@group
2012(connection-local-set-class-variables
2013 'remote-perl
2014 '((perl-command-name . "/usr/local/bin/perl")
2015 (perl-command-switch . "-e %s")))
2016@end group
2017
2018@group
2019(with-connection-local-classes '(remote-perl)
2020 do something useful)
2021@end group
2022@end example
2023@end defmac
2024
2025@defvar enable-connection-local-variables
2026If @code{nil}, connection-local variables are ignored. This variable
2027shall be changed temporarily only in special modes.
2028@end defvar
2029
1865@node Variable Aliases 2030@node Variable Aliases
1866@section Variable Aliases 2031@section Variable Aliases
1867@cindex variable aliases 2032@cindex variable aliases
diff --git a/etc/NEWS b/etc/NEWS
index 03c49907bf4..2e72fd54257 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -223,6 +223,11 @@ These local variables will thus not vanish on setting a major mode.
223** A second dir-local file (.dir-locals-2.el) is now accepted. 223** A second dir-local file (.dir-locals-2.el) is now accepted.
224See the variable 'dir-locals-file-2' for more information. 224See the variable 'dir-locals-file-2' for more information.
225 225
226+++
227** Connection-local variables can be used to specify local variables
228with a value depending on the connected remote server. For details, see
229(info "(elisp)Connection Local Variables")
230
226--- 231---
227** International domain names (IDNA) are now encoded via the new 232** International domain names (IDNA) are now encoded via the new
228puny.el library, so that one can visit web sites with non-ASCII URLs. 233puny.el library, so that one can visit web sites with non-ASCII URLs.
diff --git a/lisp/files-x.el b/lisp/files-x.el
index 05ad7f57c57..212c936414f 100644
--- a/lisp/files-x.el
+++ b/lisp/files-x.el
@@ -543,6 +543,145 @@ from the MODE alist ignoring the input argument VALUE."
543 (add-file-local-variable-prop-line (car elt) (cdr elt)))) 543 (add-file-local-variable-prop-line (car elt) (cdr elt))))
544 544
545 545
546;;; connection-local variables.
547
548;;;###autoload
549(defvar enable-connection-local-variables t
550 "Non-nil means enable use of connection-local variables.")
551
552(defvar connection-local-variables-alist nil
553 "Alist of connection-local variable settings in the current buffer.
554Each element in this list has the form (VAR . VALUE), where VAR
555is a connection-local variable (a symbol) and VALUE is its value.
556The actual value in the buffer may differ from VALUE, if it is
557changed by the user.")
558(make-variable-buffer-local 'connection-local-variables-alist)
559(setq ignored-local-variables
560 (cons 'connection-local-variables-alist ignored-local-variables))
561
562(defvar connection-local-class-alist '()
563 "Alist mapping connection-local variable classes (symbols) to variable lists.
564Each element in this list has the form (CLASS VARIABLES).
565CLASS is the name of a variable class (a symbol).
566VARIABLES is a list that declares connection-local variables for
567CLASS. An element in VARIABLES is an alist whose elements are of
568the form (VAR . VALUE).")
569
570(defvar connection-local-criteria-alist '()
571 "Alist mapping criteria to connection-local variable classes (symbols).
572Each element in this list has the form (CRITERIA CLASSES).
573CRITERIA is either a regular expression identifying a remote
574server, or a function with one argument IDENTIFICATION, which
575returns non-nil when a remote server shall apply CLASS'es
576variables. If CRITERIA is nil, it always applies.
577CLASSES is a list of variable classes (symbols).")
578
579(defsubst connection-local-get-classes (criteria &optional identification)
580 "Return the connection-local classes list for CRITERIA.
581CRITERIA is either a regular expression identifying a remote
582server, or a function with one argument IDENTIFICATION, which
583returns non-nil when a remote server shall apply CLASS'es
584variables. If CRITERIA is nil, it always applies.
585If IDENTIFICATION is non-nil, CRITERIA must be nil, or match
586IDENTIFICATION accordingly."
587 (and (cond ((null identification))
588 ((not (stringp identification))
589 (error "Wrong identification `%s'" identification))
590 ((null criteria))
591 ((stringp criteria) (string-match criteria identification))
592 ((functionp criteria) (funcall criteria identification))
593 (t "Wrong criteria `%s'" criteria))
594 (cdr (assoc criteria connection-local-criteria-alist))))
595
596;;;###autoload
597(defun connection-local-set-classes (criteria &rest classes)
598 "Add CLASSES for remote servers.
599CRITERIA is either a regular expression identifying a remote
600server, or a function with one argument IDENTIFICATION, which
601returns non-nil when a remote server shall apply CLASS'es
602variables. If CRITERIA is nil, it always applies.
603CLASSES are the names of a variable class (a symbol).
604
605When a connection to a remote server is opened and CRITERIA
606matches to that server, the connection-local variables from CLASSES
607are applied to the corresponding process buffer. The variables
608for a class are defined using `connection-local-set-class-variables'."
609 (unless (or (null criteria) (stringp criteria) (functionp criteria))
610 (error "Wrong criteria `%s'" criteria))
611 (dolist (class classes)
612 (unless (assq class connection-local-class-alist)
613 (error "No such class `%s'" (symbol-name class))))
614 (let ((slot (assoc criteria connection-local-criteria-alist)))
615 (if slot
616 (setcdr slot (delete-dups (append (cdr slot) classes)))
617 (setq connection-local-criteria-alist
618 (cons (cons criteria (delete-dups classes))
619 connection-local-criteria-alist)))))
620
621(defsubst connection-local-get-class-variables (class)
622 "Return the connection-local variable list for CLASS."
623 (cdr (assq class connection-local-class-alist)))
624
625;;;###autoload
626(defun connection-local-set-class-variables (class variables)
627 "Map the symbol CLASS to a list of variable settings.
628VARIABLES is a list that declares connection-local variables for
629the class. An element in VARIABLES is an alist whose elements
630are of the form (VAR . VALUE).
631
632When a connection to a remote server is opened, the server's
633classes are found. A server may be assigned a class using
634`connection-local-set-class'. Then variables are set in the
635server's process buffer according to the VARIABLES list of the
636class. The list is processed in order."
637 (setf (alist-get class connection-local-class-alist) variables))
638
639(defun hack-connection-local-variables ()
640 "Read per-connection local variables for the current buffer.
641Store the connection-local variables in `connection-local-variables-alist'.
642
643This does nothing if `enable-connection-local-variables' is nil."
644 (let ((identification (file-remote-p default-directory)))
645 (when (and enable-connection-local-variables identification)
646 ;; Loop over criteria.
647 (dolist (criteria (mapcar 'car connection-local-criteria-alist))
648 ;; Filter classes which map identification.
649 (dolist (class (connection-local-get-classes criteria identification))
650 ;; Loop over variables.
651 (dolist (variable (connection-local-get-class-variables class))
652 (unless (assq (car variable) connection-local-variables-alist)
653 (push variable connection-local-variables-alist))))))))
654
655;;;###autoload
656(defun hack-connection-local-variables-apply ()
657 "Apply connection-local variables identified by `default-directory'.
658Other local variables, like file-local and dir-local variables,
659will not be changed."
660 (hack-connection-local-variables)
661 (let ((file-local-variables-alist
662 (copy-tree connection-local-variables-alist)))
663 (hack-local-variables-apply)))
664
665;;;###autoload
666(defmacro with-connection-local-classes (classes &rest body)
667 "Apply connection-local variables according to CLASSES in current buffer.
668Execute BODY, and unwind connection local variables."
669 (declare (indent 1) (debug t))
670 `(let ((enable-connection-local-variables t)
671 (old-buffer-local-variables (buffer-local-variables))
672 connection-local-variables-alist connection-local-criteria-alist)
673 (apply 'connection-local-set-classes "" ,classes)
674 (hack-connection-local-variables-apply)
675 (unwind-protect
676 (progn ,@body)
677 ;; Cleanup.
678 (dolist (variable connection-local-variables-alist)
679 (let ((elt (assq (car variable) old-buffer-local-variables)))
680 (if elt
681 (set (make-local-variable (car elt)) (cdr elt))
682 (kill-local-variable (car variable))))))))
683
684
546 685
547(provide 'files-x) 686(provide 'files-x)
548 687
diff --git a/lisp/net/tramp-adb.el b/lisp/net/tramp-adb.el
index 259b1cb1b88..1aae0ecfffd 100644
--- a/lisp/net/tramp-adb.el
+++ b/lisp/net/tramp-adb.el
@@ -1243,6 +1243,9 @@ connection if a previous connection has died for some reason."
1243 (read (current-buffer))) 1243 (read (current-buffer)))
1244 ":" 'omit)) 1244 ":" 'omit))
1245 1245
1246 ;; Set connection-local variables.
1247 (tramp-set-connection-local-variables vec)
1248
1246 ;; Mark it as connected. 1249 ;; Mark it as connected.
1247 (tramp-set-connection-property p "connected" t))))))) 1250 (tramp-set-connection-property p "connected" t)))))))
1248 1251
diff --git a/lisp/net/tramp-gvfs.el b/lisp/net/tramp-gvfs.el
index 637c2a70ab1..a84097cfc4d 100644
--- a/lisp/net/tramp-gvfs.el
+++ b/lisp/net/tramp-gvfs.el
@@ -1723,6 +1723,9 @@ connection if a previous connection has died for some reason."
1723 (tramp-get-file-property vec "/" "fuse-mountpoint" "") "/") 1723 (tramp-get-file-property vec "/" "fuse-mountpoint" "") "/")
1724 (tramp-error vec 'file-error "FUSE mount denied")) 1724 (tramp-error vec 'file-error "FUSE mount denied"))
1725 1725
1726 ;; Set connection-local variables.
1727 (tramp-set-connection-local-variables vec)
1728
1726 ;; Mark it as connected. 1729 ;; Mark it as connected.
1727 (tramp-set-connection-property 1730 (tramp-set-connection-property
1728 (tramp-get-connection-process vec) "connected" t)))) 1731 (tramp-get-connection-process vec) "connected" t))))
diff --git a/lisp/net/tramp-gw.el b/lisp/net/tramp-gw.el
index b631072ad1a..8f8f107ec10 100644
--- a/lisp/net/tramp-gw.el
+++ b/lisp/net/tramp-gw.el
@@ -333,5 +333,7 @@ password in password cache. This is done for the first try only."
333;; * Provide descriptive Commentary. 333;; * Provide descriptive Commentary.
334;; 334;;
335;; * Enable it for several gateway processes in parallel. 335;; * Enable it for several gateway processes in parallel.
336;;
337;; * Use `url-https-proxy-connect' as of Emacs 26.
336 338
337;;; tramp-gw.el ends here 339;;; tramp-gw.el ends here
diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el
index 6a190b0e9fe..1682b16fe02 100644
--- a/lisp/net/tramp-sh.el
+++ b/lisp/net/tramp-sh.el
@@ -518,6 +518,7 @@ The string is used in `tramp-methods'.")
518;; FreeBSD: /usr/bin:/bin:/usr/sbin:/sbin: - beware trailing ":"! 518;; FreeBSD: /usr/bin:/bin:/usr/sbin:/sbin: - beware trailing ":"!
519;; Darwin: /usr/bin:/bin:/usr/sbin:/sbin 519;; Darwin: /usr/bin:/bin:/usr/sbin:/sbin
520;; IRIX64: /usr/bin 520;; IRIX64: /usr/bin
521;; QNAP QTS: ---
521;;;###tramp-autoload 522;;;###tramp-autoload
522(defcustom tramp-remote-path 523(defcustom tramp-remote-path
523 '(tramp-default-remote-path "/bin" "/usr/bin" "/sbin" "/usr/sbin" 524 '(tramp-default-remote-path "/bin" "/usr/bin" "/sbin" "/usr/sbin"
@@ -4918,6 +4919,9 @@ connection if a previous connection has died for some reason."
4918 (setq options "" 4919 (setq options ""
4919 target-alist (cdr target-alist))) 4920 target-alist (cdr target-alist)))
4920 4921
4922 ;; Set connection-local variables.
4923 (tramp-set-connection-local-variables vec)
4924
4921 ;; Make initial shell settings. 4925 ;; Make initial shell settings.
4922 (tramp-open-connection-setup-interactive-shell p vec) 4926 (tramp-open-connection-setup-interactive-shell p vec)
4923 4927
diff --git a/lisp/net/tramp-smb.el b/lisp/net/tramp-smb.el
index 0c8ecf470e1..7c600702cae 100644
--- a/lisp/net/tramp-smb.el
+++ b/lisp/net/tramp-smb.el
@@ -1916,6 +1916,9 @@ If ARGUMENT is non-nil, use it as argument for
1916 (tramp-set-connection-property p "smb-share" share) 1916 (tramp-set-connection-property p "smb-share" share)
1917 (tramp-set-connection-property p "chunksize" 1) 1917 (tramp-set-connection-property p "chunksize" 1)
1918 1918
1919 ;; Set connection-local variables.
1920 (tramp-set-connection-local-variables vec)
1921
1919 ;; Mark it as connected. 1922 ;; Mark it as connected.
1920 (tramp-set-connection-property p "connected" t)) 1923 (tramp-set-connection-property p "connected" t))
1921 1924
diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el
index c92c705c26c..5d56fdf1104 100644
--- a/lisp/net/tramp.el
+++ b/lisp/net/tramp.el
@@ -1338,6 +1338,15 @@ In case a second asynchronous communication has been started, it is different
1338from the default one." 1338from the default one."
1339 (get-process (tramp-get-connection-name vec))) 1339 (get-process (tramp-get-connection-name vec)))
1340 1340
1341(defun tramp-set-connection-local-variables (vec)
1342 "Set connection-local variables in the connection buffer used for VEC.
1343If connection-local variables are not supported by this Emacs
1344version, the function does nothing."
1345 ;; `tramp-get-connection-buffer' sets proper `default-directory'."
1346 (with-current-buffer (tramp-get-connection-buffer vec)
1347 ;; `hack-connection-local-variables-apply' exists since Emacs 26.1.
1348 (tramp-compat-funcall 'hack-connection-local-variables-apply)))
1349
1341(defun tramp-debug-buffer-name (vec) 1350(defun tramp-debug-buffer-name (vec)
1342 "A name for the debug buffer for VEC." 1351 "A name for the debug buffer for VEC."
1343 ;; We must use `tramp-file-name-real-host', because for gateway 1352 ;; We must use `tramp-file-name-real-host', because for gateway
@@ -4325,13 +4334,6 @@ Only works for Bourne-like shells."
4325;; strange when doing zerop, we should kill the process and start 4334;; strange when doing zerop, we should kill the process and start
4326;; again. (Greg Stark) 4335;; again. (Greg Stark)
4327;; 4336;;
4328;; * Implement a general server-local-variable mechanism, as there are
4329;; probably other variables that need different values for different
4330;; servers too. The user could then configure a variable (such as
4331;; tramp-server-local-variable-alist) to define any such variables
4332;; that they need to, which would then be let bound as appropriate
4333;; in tramp functions. (Jason Rumney)
4334;;
4335;; * Make shadowfile.el grok Tramp filenames. (Bug#4526, Bug#4846) 4337;; * Make shadowfile.el grok Tramp filenames. (Bug#4526, Bug#4846)
4336;; 4338;;
4337;; * I was wondering if it would be possible to use tramp even if I'm 4339;; * I was wondering if it would be possible to use tramp even if I'm
diff --git a/test/lisp/files-x-tests.el b/test/lisp/files-x-tests.el
new file mode 100644
index 00000000000..8f2c11d391c
--- /dev/null
+++ b/test/lisp/files-x-tests.el
@@ -0,0 +1,297 @@
1;;; files-x-tests.el --- tests for files-x.el.
2
3;; Copyright (C) 2016 Free Software Foundation, Inc.
4
5;; Author: Michael Albinus <michael.albinus@gmx.de>
6
7;; This file is part of GNU Emacs.
8
9;; GNU Emacs is free software: you can redistribute it and/or modify
10;; it under the terms of the GNU General Public License as published by
11;; the Free Software Foundation, either version 3 of the License, or
12;; (at your option) any later version.
13
14;; GNU Emacs is distributed in the hope that it will be useful,
15;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17;; GNU General Public License for more details.
18
19;; You should have received a copy of the GNU General Public License
20;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
21
22;;; Code:
23
24(require 'ert)
25(require 'files-x)
26
27(defvar files-x-test--criteria1 "my-user@my-remote-host")
28(defvar files-x-test--criteria2
29 (lambda (identification)
30 (string-match "another-user@my-remote-host" identification)))
31(defvar files-x-test--criteria3 nil)
32
33(defvar files-x-test--variables1
34 '((remote-shell-file-name . "/bin/bash")
35 (remote-shell-command-switch . "-c")
36 (remote-shell-interactive-switch . "-i")
37 (remote-shell-login-switch . "-l")))
38(defvar files-x-test--variables2
39 '((remote-shell-file-name . "/bin/ksh")))
40(defvar files-x-test--variables3
41 '((remote-null-device . "/dev/null")))
42(defvar files-x-test--variables4
43 '((remote-null-device . "null")))
44
45(ert-deftest files-x-test-connection-local-set-class-variables ()
46 "Test setting connection-local class variables."
47
48 ;; Declare (CLASS VARIABLES) objects.
49 (let (connection-local-class-alist connection-local-criteria-alist)
50 (connection-local-set-class-variables 'remote-bash files-x-test--variables1)
51 (should
52 (equal
53 (connection-local-get-class-variables 'remote-bash)
54 files-x-test--variables1))
55
56 (connection-local-set-class-variables 'remote-ksh files-x-test--variables2)
57 (should
58 (equal
59 (connection-local-get-class-variables 'remote-ksh)
60 files-x-test--variables2))
61
62 (connection-local-set-class-variables
63 'remote-nullfile files-x-test--variables3)
64 (should
65 (equal
66 (connection-local-get-class-variables 'remote-nullfile)
67 files-x-test--variables3))
68
69 ;; A redefinition overwrites existing values.
70 (connection-local-set-class-variables
71 'remote-nullfile files-x-test--variables4)
72 (should
73 (equal
74 (connection-local-get-class-variables 'remote-nullfile)
75 files-x-test--variables4))))
76
77(ert-deftest files-x-test-connection-local-set-classes ()
78 "Test setting connection-local classes."
79
80 ;; Declare (CRITERIA CLASSES) objects.
81 (let (connection-local-class-alist connection-local-criteria-alist)
82 (connection-local-set-class-variables 'remote-bash files-x-test--variables1)
83 (connection-local-set-class-variables 'remote-ksh files-x-test--variables2)
84 (connection-local-set-class-variables
85 'remote-nullfile files-x-test--variables3)
86
87 (connection-local-set-classes
88 files-x-test--criteria1 'remote-bash 'remote-ksh)
89 (should
90 (equal
91 (connection-local-get-classes files-x-test--criteria1)
92 '(remote-bash remote-ksh)))
93
94 (connection-local-set-classes files-x-test--criteria2 'remote-ksh)
95 (should
96 (equal
97 (connection-local-get-classes files-x-test--criteria2)
98 '(remote-ksh)))
99 ;; A further call adds classes.
100 (connection-local-set-classes files-x-test--criteria2 'remote-nullfile)
101 (should
102 (equal
103 (connection-local-get-classes files-x-test--criteria2)
104 '(remote-ksh remote-nullfile)))
105 ;; Adding existing classes doesn't matter.
106 (connection-local-set-classes
107 files-x-test--criteria2 'remote-bash 'remote-nullfile)
108 (should
109 (equal
110 (connection-local-get-classes files-x-test--criteria2)
111 '(remote-ksh remote-nullfile remote-bash)))
112
113 ;; An empty variable list is accepted (but makes no sense).
114 (connection-local-set-classes files-x-test--criteria3)
115 (should-not (connection-local-get-classes files-x-test--criteria3))
116
117 ;; Using a nil criteria also works. Duplicate classes are trashed.
118 (connection-local-set-classes
119 files-x-test--criteria3 'remote-bash 'remote-ksh 'remote-ksh 'remote-bash)
120 (should
121 (equal
122 (connection-local-get-classes files-x-test--criteria3)
123 '(remote-bash remote-ksh)))
124
125 ;; A criteria other than nil, regexp or lambda function is wrong.
126 (should-error (connection-local-set-classes 'dummy))))
127
128(ert-deftest files-x-test-hack-connection-local-variables-apply ()
129 "Test setting connection-local variables."
130
131 (let (connection-local-class-alist connection-local-criteria-alist)
132
133 (connection-local-set-class-variables 'remote-bash files-x-test--variables1)
134 (connection-local-set-class-variables 'remote-ksh files-x-test--variables2)
135 (connection-local-set-class-variables
136 'remote-nullfile files-x-test--variables3)
137
138 (connection-local-set-classes
139 files-x-test--criteria1 'remote-bash 'remote-ksh)
140 (connection-local-set-classes
141 files-x-test--criteria2 'remote-ksh 'remote-nullfile)
142
143 ;; Apply the variables.
144 (with-temp-buffer
145 (let ((enable-connection-local-variables t)
146 (default-directory "/sudo:my-user@my-remote-host:"))
147 (should-not connection-local-variables-alist)
148 (should-not (local-variable-p 'remote-shell-file-name))
149 (should-not (boundp 'remote-shell-file-name))
150 (hack-connection-local-variables-apply)
151 ;; All connection-local variables are set. They apply in
152 ;; reverse order in `connection-local-variables-alist'. The
153 ;; settings from `remote-ksh' are not contained, because they
154 ;; declare same variables as in `remote-bash'.
155 (should
156 (equal connection-local-variables-alist
157 (nreverse (copy-tree files-x-test--variables1))))
158 ;; The variables exist also as local variables.
159 (should (local-variable-p 'remote-shell-file-name))
160 ;; The proper variable value is set.
161 (should
162 (string-equal (symbol-value 'remote-shell-file-name) "/bin/bash"))))
163
164 ;; The second test case.
165 (with-temp-buffer
166 (let ((enable-connection-local-variables t)
167 (default-directory "/ssh:another-user@my-remote-host:"))
168 (should-not connection-local-variables-alist)
169 (should-not (local-variable-p 'remote-shell-file-name))
170 (should-not (boundp 'remote-shell-file-name))
171 (hack-connection-local-variables-apply)
172 ;; All connection-local variables are set. They apply in
173 ;; reverse order in `connection-local-variables-alist'.
174 (should
175 (equal connection-local-variables-alist
176 (append
177 (nreverse (copy-tree files-x-test--variables3))
178 (nreverse (copy-tree files-x-test--variables2)))))
179 ;; The variables exist also as local variables.
180 (should (local-variable-p 'remote-shell-file-name))
181 ;; The proper variable value is set.
182 (should
183 (string-equal (symbol-value 'remote-shell-file-name) "/bin/ksh"))))
184
185 ;; The third test case. Both `files-x-test--criteria1' and
186 ;; `files-x-test--criteria3' apply, but there are no double
187 ;; entries.
188 (connection-local-set-classes
189 files-x-test--criteria3 'remote-bash 'remote-ksh)
190 (with-temp-buffer
191 (let ((enable-connection-local-variables t)
192 (default-directory "/sudo:my-user@my-remote-host:"))
193 (should-not connection-local-variables-alist)
194 (should-not (local-variable-p 'remote-shell-file-name))
195 (should-not (boundp 'remote-shell-file-name))
196 (hack-connection-local-variables-apply)
197 ;; All connection-local variables are set. They apply in
198 ;; reverse order in `connection-local-variables-alist'. The
199 ;; settings from `remote-ksh' are not contained, because they
200 ;; declare same variables as in `remote-bash'.
201 (should
202 (equal connection-local-variables-alist
203 (nreverse (copy-tree files-x-test--variables1))))
204 ;; The variables exist also as local variables.
205 (should (local-variable-p 'remote-shell-file-name))
206 ;; The proper variable value is set.
207 (should
208 (string-equal (symbol-value 'remote-shell-file-name) "/bin/bash"))))
209
210 ;; When `enable-connection-local-variables' is nil, nothing happens.
211 (with-temp-buffer
212 (let ((enable-connection-local-variables nil)
213 (default-directory "/ssh:another-user@my-remote-host:"))
214 (should-not connection-local-variables-alist)
215 (should-not (local-variable-p 'remote-shell-file-name))
216 (should-not (boundp 'remote-shell-file-name))
217 (hack-connection-local-variables-apply)
218 (should-not connection-local-variables-alist)
219 (should-not (local-variable-p 'remote-shell-file-name))
220 (should-not (boundp 'remote-shell-file-name))))))
221
222(ert-deftest files-x-test-with-connection-local-classes ()
223 "Test setting connection-local variables."
224
225 (let (connection-local-class-alist connection-local-criteria-alist)
226 (connection-local-set-class-variables 'remote-bash files-x-test--variables1)
227 (connection-local-set-class-variables 'remote-ksh files-x-test--variables2)
228 (connection-local-set-class-variables
229 'remote-nullfile files-x-test--variables3)
230 (connection-local-set-classes
231 files-x-test--criteria3 'remote-ksh 'remote-nullfile)
232
233 (with-temp-buffer
234 (let ((enable-connection-local-variables t)
235 (default-directory "/sudo:my-user@my-remote-host:"))
236 (hack-connection-local-variables-apply)
237
238 ;; All connection-local variables are set. They apply in
239 ;; reverse order in `connection-local-variables-alist'.
240 (should
241 (equal connection-local-variables-alist
242 (append
243 (nreverse (copy-tree files-x-test--variables3))
244 (nreverse (copy-tree files-x-test--variables2)))))
245 ;; The variables exist also as local variables.
246 (should (local-variable-p 'remote-shell-file-name))
247 (should (local-variable-p 'remote-null-device))
248 ;; The proper variable values are set.
249 (should
250 (string-equal (symbol-value 'remote-shell-file-name) "/bin/ksh"))
251 (should
252 (string-equal (symbol-value 'remote-null-device) "/dev/null"))
253
254 ;; A candidate connection-local variable is not bound yet.
255 (should-not (local-variable-p 'remote-shell-command-switch))
256
257 ;; Use the macro.
258 (with-connection-local-classes '(remote-bash remote-ksh)
259 ;; All connection-local variables are set. They apply in
260 ;; reverse order in `connection-local-variables-alist'.
261 ;; This variable keeps only the variables to be set inside
262 ;; the macro.
263 (should
264 (equal connection-local-variables-alist
265 (nreverse (copy-tree files-x-test--variables1))))
266 ;; The variables exist also as local variables.
267 (should (local-variable-p 'remote-shell-file-name))
268 (should (local-variable-p 'remote-shell-command-switch))
269 ;; The proper variable values are set. The settings from
270 ;; `remote-bash' overwrite the same variables as in
271 ;; `remote-ksh'.
272 (should
273 (string-equal (symbol-value 'remote-shell-file-name) "/bin/bash"))
274 (should
275 (string-equal (symbol-value 'remote-shell-command-switch) "-c")))
276
277 ;; Everything is rewound. The old variable values are reset.
278 (should
279 (equal connection-local-variables-alist
280 (append
281 (nreverse (copy-tree files-x-test--variables3))
282 (nreverse (copy-tree files-x-test--variables2)))))
283 ;; The variables exist also as local variables.
284 (should (local-variable-p 'remote-shell-file-name))
285 (should (local-variable-p 'remote-null-device))
286 ;; The proper variable values are set. The settings from
287 ;; `remote-ksh' are back.
288 (should
289 (string-equal (symbol-value 'remote-shell-file-name) "/bin/ksh"))
290 (should
291 (string-equal (symbol-value 'remote-null-device) "/dev/null"))
292
293 ;; The variable set temporarily is not unbound, again.
294 (should-not (local-variable-p 'remote-shell-command-switch))))))
295
296(provide 'files-x-tests)
297;;; files-x-tests.el ends here