Commit 35a86f0b authored by Michael Albinus's avatar Michael Albinus

Implement quoting the local part of a remote file name

* doc/emacs/files.texi (Quoted File Names):
* etc/NEWS: Mention quoting the local part of a remote file name.

* lisp/net/tramp.el (tramp-dissect-file-name): Check with
`tramp-tramp-file-p'.
(tramp-quoted-name-p, tramp-quote-name, tramp-unquote-name):
New defsubst.
(tramp-handle-substitute-in-file-name)
(tramp-handle-make-auto-save-file-name): Handle quoted files.
(tramp-shell-quote-argument): Unquote argument.

* lisp/net/tramp-sh.el (tramp-sh-handle-file-truename):
Handle quoted files.

* test/lisp/net/tramp-tests.el (tramp--test-expensive-test): New defvar.
(tramp--test-make-temp-name): New argument QUOTED.
(tramp-test01-file-name-syntax)
(tramp-test02-file-name-dissect)
(tramp-test04-substitute-in-file-name)
(tramp-test05-expand-file-name, tramp-test07-file-exists-p)
(tramp-test08-file-local-copy)
(tramp-test09-insert-file-contents)
(tramp-test10-write-region, tramp-test11-copy-file)
(tramp-test12-rename-file, tramp-test13-make-directory)
(tramp-test14-delete-directory, tramp-test15-copy-directory)
(tramp-test16-directory-files)
(tramp-test17-insert-directory)
(tramp-test18-file-attributes)
(tramp-test19-directory-files-and-attributes)
(tramp-test20-file-modes, tramp-test21-file-links)
(tramp-test22-file-times, tramp-test23-visited-file-modtime)
(tramp-test24-file-name-completion, tramp-test25-load)
(tramp-test26-process-file, tramp-test27-start-file-process)
(tramp-test28-shell-command, tramp-test30-vc-registered)
(tramp-test31-make-auto-save-file-name)
(tramp--test-check-files)
(tramp-test35-asynchronous-requests): Test also quoted file names.
(tramp--test-shell-command-to-string-asynchronously): Rename.
(tramp-test29-environment-variables): Use it.
parent 35d54709
......@@ -1870,6 +1870,11 @@ prevent it from being treated as a remote file name. Thus, if you have
a directory named @file{/foo:} and a file named @file{bar} in it, you
can refer to that file in Emacs as @samp{/:/foo:/bar}.
If you want to quote only special characters in the local part of a
remote file name, you can quote just the local part.
@samp{/baz:/:/foo:/bar} refers to the file @file{bar} of directory
@file{/foo:} on the host @file{baz}.
@samp{/:} can also prevent @samp{~} from being treated as a special
character for a user's home directory. For example, @file{/:/tmp/~hack}
refers to a file whose name is @file{~hack} in directory @file{/tmp}.
......
......@@ -268,6 +268,12 @@ variable of this kind to swap modifiers in Emacs.
---
** New input methods: 'cyrillic-tuvan', 'polish-prefix'.
+++
** File name quoting by adding the prefix "/:" is now possible for the
local part of a remote file name. Thus, if you have a directory named
"/~" on the remote host "foo", you can prevent it from being
substituted by a home directory by writing it as "/foo:/:/~/file".
* Editing Changes in Emacs 26.1
......
......@@ -1146,7 +1146,9 @@ target of the symlink differ."
(tramp-make-tramp-file-name
method user host
(with-tramp-file-property v localname "file-truename"
(let ((result nil)) ; result steps in reverse order
(let ((result nil) ; result steps in reverse order
(quoted (tramp-quoted-name-p localname))
(localname (tramp-unquote-name localname)))
(tramp-message v 4 "Finding true name for `%s'" filename)
(cond
;; Use GNU readlink --canonicalize-missing where available.
......@@ -1241,6 +1243,7 @@ target of the symlink differ."
(when (string= "" result)
(setq result "/")))))
(when quoted (setq result (tramp-quote-name result)))
(tramp-message v 4 "True name of `%s' is `%s'" localname result)
result))))
......
......@@ -1239,9 +1239,9 @@ localname (file name on remote host) and hop. If NODEFAULT is
non-nil, the file name parts are not expanded to their default
values."
(save-match-data
(unless (tramp-tramp-file-p name)
(tramp-compat-user-error nil "Not a Tramp file name: \"%s\"" name))
(let ((match (string-match (nth 0 tramp-file-name-structure) name)))
(unless match
(tramp-compat-user-error nil "Not a Tramp file name: \"%s\"" name))
(let ((method (match-string (nth 1 tramp-file-name-structure) name))
(user (match-string (nth 2 tramp-file-name-structure) name))
(host (match-string (nth 3 tramp-file-name-structure) name))
......@@ -1679,6 +1679,27 @@ FILE must be a local file name on a connection identified via VEC."
(font-lock-add-keywords
'emacs-lisp-mode '("\\<with-tramp-connection-property\\>"))
(defsubst tramp-quoted-name-p (name)
"Whether NAME is quoted with prefix \"/:\".
If NAME is a remote file name, check the local part of NAME."
(string-match "^/:" (or (file-remote-p name 'localname) name)))
(defsubst tramp-quote-name (name)
"Add the quotation prefix \"/:\" to file NAME.
If NAME is a remote file name, the local part of NAME is quoted."
(concat (file-remote-p name) "/:" (or (file-remote-p name 'localname) name)))
(defsubst tramp-unquote-name (name)
"Remove quotation prefix \"/:\" from file NAME.
If NAME is a remote file name, the local part of NAME is unquoted."
(save-match-data
(let ((localname (or (file-remote-p name 'localname) name)))
(when (tramp-quoted-name-p localname)
(setq
localname
(replace-match (if (= (length localname) 2) "/" "") nil t localname)))
(concat (file-remote-p name) localname))))
(defun tramp-drop-volume-letter (name)
"Cut off unnecessary drive letter from file NAME.
The functions `tramp-*-handle-expand-file-name' call `expand-file-name'
......@@ -3323,20 +3344,23 @@ User is always nil."
(defun tramp-handle-substitute-in-file-name (filename)
"Like `substitute-in-file-name' for Tramp files.
\"//\" and \"/~\" substitute only in the local filename part."
;; First, we must replace environment variables.
(setq filename (tramp-replace-environment-variables filename))
(with-parsed-tramp-file-name filename nil
;; Ignore in LOCALNAME everything before "//" or "/~".
(when (and (stringp localname) (string-match ".+?/\\(/\\|~\\)" localname))
(setq filename
(concat (file-remote-p filename)
(replace-match "\\1" nil nil localname)))
;; "/m:h:~" does not work for completion. We use "/m:h:~/".
(when (string-match "~$" filename)
(setq filename (concat filename "/"))))
;; We do not want to replace environment variables, again.
(let (process-environment)
(tramp-run-real-handler 'substitute-in-file-name (list filename)))))
;; Check, whether the local part is a quoted file name.
(if (tramp-quoted-name-p filename)
filename
;; First, we must replace environment variables.
(setq filename (tramp-replace-environment-variables filename))
(with-parsed-tramp-file-name filename nil
;; Ignore in LOCALNAME everything before "//" or "/~".
(when (and (stringp localname) (string-match ".+?/\\(/\\|~\\)" localname))
(setq filename
(concat (file-remote-p filename)
(replace-match "\\1" nil nil localname)))
;; "/m:h:~" does not work for completion. We use "/m:h:~/".
(when (string-match "~$" filename)
(setq filename (concat filename "/"))))
;; We do not want to replace environment variables, again.
(let (process-environment)
(tramp-run-real-handler 'substitute-in-file-name (list filename))))))
(defun tramp-handle-set-visited-file-modtime (&optional time-list)
"Like `set-visited-file-modtime' for Tramp files."
......@@ -4080,7 +4104,7 @@ this file, if that variable is non-nil."
("|" . "__")
("[" . "_l")
("]" . "_r"))
(buffer-file-name))
(tramp-unquote-name (buffer-file-name)))
tramp-auto-save-directory))))
;; Run plain `make-auto-save-file-name'.
(tramp-run-real-handler 'make-auto-save-file-name nil)))
......@@ -4318,7 +4342,7 @@ T1 and T2 are time values (as returned by `current-time' for example)."
Only works for Bourne-like shells."
(let ((system-type 'not-windows))
(save-match-data
(let ((result (shell-quote-argument s))
(let ((result (shell-quote-argument (tramp-unquote-name s)))
(nl (regexp-quote (format "\\%s" tramp-rsh-end-of-line))))
(when (and (>= (length result) 2)
(string= (substring result 0 2) "\\~"))
......
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment