diff options
| author | Michael Albinus | 2016-11-14 13:56:58 +0100 |
|---|---|---|
| committer | Michael Albinus | 2016-11-14 13:56:58 +0100 |
| commit | 6647e05174ade1132a957e7e27f9ef6e96f3f9d7 (patch) | |
| tree | dc94c02f1da132fcdd15af167da56605b172d808 | |
| parent | db43613307bb05d0f43d2d5649b5bb2f29876cee (diff) | |
| download | emacs-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.texi | 165 | ||||
| -rw-r--r-- | etc/NEWS | 5 | ||||
| -rw-r--r-- | lisp/files-x.el | 139 | ||||
| -rw-r--r-- | lisp/net/tramp-adb.el | 3 | ||||
| -rw-r--r-- | lisp/net/tramp-gvfs.el | 3 | ||||
| -rw-r--r-- | lisp/net/tramp-gw.el | 2 | ||||
| -rw-r--r-- | lisp/net/tramp-sh.el | 4 | ||||
| -rw-r--r-- | lisp/net/tramp-smb.el | 3 | ||||
| -rw-r--r-- | lisp/net/tramp.el | 16 | ||||
| -rw-r--r-- | test/lisp/files-x-tests.el | 297 |
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 | |||
| 1862 | still respecting file-local variables (@pxref{File Local Variables}). | 1863 | still 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 | ||
| 1871 | different variable settings in buffers with a remote default | ||
| 1872 | directory. They are bound and set depending on the remote connection | ||
| 1873 | a buffer is dedicated to. Per default, they are set in all process | ||
| 1874 | buffers for a remote connection, but they could be applied also in | ||
| 1875 | other buffers with a remote directory. | ||
| 1876 | |||
| 1877 | @defun connection-local-set-class-variables class variables | ||
| 1878 | This 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 | ||
| 1880 | or more remote connections, and Emacs will apply those variable | ||
| 1881 | settings 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 | ||
| 1913 | This alist holds the class symbols and the associated variable | ||
| 1914 | settings. It is updated by @code{connection-local-set-class-variables}. | ||
| 1915 | @end defvar | ||
| 1916 | |||
| 1917 | @defun connection-local-set-classes criteria &rest classes | ||
| 1918 | This function assigns @var{classes}, which are symbols, to all remote | ||
| 1919 | connections identified by @var{criteria}. @var{criteria} is either a | ||
| 1920 | regular expression identifying a remote server, or a function with one | ||
| 1921 | argument @var{identification}, which must return non-nil when a remote | ||
| 1922 | server shall apply @var{classes} variables, or @code{nil}. | ||
| 1923 | |||
| 1924 | If @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 | ||
| 1926 | the 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. | ||
| 1941 | Therefore, 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, | ||
| 1950 | the 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} | ||
| 1975 | will be applied to any buffer with a matching remote directory, when | ||
| 1976 | activated by @code{hack-connection-local-variables-apply}. Any class | ||
| 1977 | of @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 | ||
| 1982 | This alist contains remote server identifications and their assigned | ||
| 1983 | class names. The function @code{connection-local-set-classes} updates | ||
| 1984 | this list. | ||
| 1985 | @end defvar | ||
| 1986 | |||
| 1987 | @defun hack-connection-local-variables | ||
| 1988 | This function collects applicable connection-local variables in | ||
| 1989 | @code{connection-local-variables-alist} that is local to the buffer, | ||
| 1990 | without applying them. Whether a connection-local variable is | ||
| 1991 | applicable is specified by the remote identifier of a buffer, | ||
| 1992 | evaluated by @code{(file-remote-p default-directory)}. | ||
| 1993 | @end defun | ||
| 1994 | |||
| 1995 | @defun hack-connection-local-variables-apply | ||
| 1996 | This function looks for connection-local variables, and immediately | ||
| 1997 | applies them in the current buffer. It is called per default for | ||
| 1998 | every process-buffer related to a remote connection. For other remote | ||
| 1999 | buffers, it could be called by any mode. | ||
| 2000 | @end defun | ||
| 2001 | |||
| 2002 | @defmac with-connection-local-classes classes &rest body | ||
| 2003 | All connection-local variables, which are specified by a class in | ||
| 2004 | @var{CLASSES}, are applied. An implicit binding of the classes to the | ||
| 2005 | remote connection is enabled. | ||
| 2006 | |||
| 2007 | After that, @var{BODY} is executed, and the connection-local variables | ||
| 2008 | are 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 | ||
| 2026 | If @code{nil}, connection-local variables are ignored. This variable | ||
| 2027 | shall 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 |
| @@ -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. |
| 224 | See the variable 'dir-locals-file-2' for more information. | 224 | See the variable 'dir-locals-file-2' for more information. |
| 225 | 225 | ||
| 226 | +++ | ||
| 227 | ** Connection-local variables can be used to specify local variables | ||
| 228 | with 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 |
| 228 | puny.el library, so that one can visit web sites with non-ASCII URLs. | 233 | puny.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. | ||
| 554 | Each element in this list has the form (VAR . VALUE), where VAR | ||
| 555 | is a connection-local variable (a symbol) and VALUE is its value. | ||
| 556 | The actual value in the buffer may differ from VALUE, if it is | ||
| 557 | changed 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. | ||
| 564 | Each element in this list has the form (CLASS VARIABLES). | ||
| 565 | CLASS is the name of a variable class (a symbol). | ||
| 566 | VARIABLES is a list that declares connection-local variables for | ||
| 567 | CLASS. An element in VARIABLES is an alist whose elements are of | ||
| 568 | the form (VAR . VALUE).") | ||
| 569 | |||
| 570 | (defvar connection-local-criteria-alist '() | ||
| 571 | "Alist mapping criteria to connection-local variable classes (symbols). | ||
| 572 | Each element in this list has the form (CRITERIA CLASSES). | ||
| 573 | CRITERIA is either a regular expression identifying a remote | ||
| 574 | server, or a function with one argument IDENTIFICATION, which | ||
| 575 | returns non-nil when a remote server shall apply CLASS'es | ||
| 576 | variables. If CRITERIA is nil, it always applies. | ||
| 577 | CLASSES 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. | ||
| 581 | CRITERIA is either a regular expression identifying a remote | ||
| 582 | server, or a function with one argument IDENTIFICATION, which | ||
| 583 | returns non-nil when a remote server shall apply CLASS'es | ||
| 584 | variables. If CRITERIA is nil, it always applies. | ||
| 585 | If IDENTIFICATION is non-nil, CRITERIA must be nil, or match | ||
| 586 | IDENTIFICATION 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. | ||
| 599 | CRITERIA is either a regular expression identifying a remote | ||
| 600 | server, or a function with one argument IDENTIFICATION, which | ||
| 601 | returns non-nil when a remote server shall apply CLASS'es | ||
| 602 | variables. If CRITERIA is nil, it always applies. | ||
| 603 | CLASSES are the names of a variable class (a symbol). | ||
| 604 | |||
| 605 | When a connection to a remote server is opened and CRITERIA | ||
| 606 | matches to that server, the connection-local variables from CLASSES | ||
| 607 | are applied to the corresponding process buffer. The variables | ||
| 608 | for 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. | ||
| 628 | VARIABLES is a list that declares connection-local variables for | ||
| 629 | the class. An element in VARIABLES is an alist whose elements | ||
| 630 | are of the form (VAR . VALUE). | ||
| 631 | |||
| 632 | When a connection to a remote server is opened, the server's | ||
| 633 | classes are found. A server may be assigned a class using | ||
| 634 | `connection-local-set-class'. Then variables are set in the | ||
| 635 | server's process buffer according to the VARIABLES list of the | ||
| 636 | class. 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. | ||
| 641 | Store the connection-local variables in `connection-local-variables-alist'. | ||
| 642 | |||
| 643 | This 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'. | ||
| 658 | Other local variables, like file-local and dir-local variables, | ||
| 659 | will 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. | ||
| 668 | Execute 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 | |||
| 1338 | from the default one." | 1338 | from 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. | ||
| 1343 | If connection-local variables are not supported by this Emacs | ||
| 1344 | version, 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 | ||