diff options
| author | Michael Albinus | 2017-10-20 12:46:54 +0200 |
|---|---|---|
| committer | Michael Albinus | 2017-10-20 12:46:54 +0200 |
| commit | b500e06f4d05dc094b79f8f2c063e070a5a3306e (patch) | |
| tree | e0d6131de893be18d6217f7709a40a5bedd2c72d /lisp | |
| parent | d815de017bb531fed751ee0515ed90b73d7a9936 (diff) | |
| download | emacs-b500e06f4d05dc094b79f8f2c063e070a5a3306e.tar.gz emacs-b500e06f4d05dc094b79f8f2c063e070a5a3306e.zip | |
Fix Bug#28896
* lisp/net/tramp-adb.el (tramp-adb-handle-rename-file):
* lisp/net/tramp-gvfs.el (tramp-gvfs-do-copy-or-rename-file):
* lisp/net/tramp-sh.el (tramp-do-copy-or-rename-file): Handle FILENAME
being a directory. (Bug#28896)
* test/lisp/net/tramp-tests.el (tramp-test11-copy-file)
(tramp-test12-rename-file): Test also FILENAME being a directory.
Diffstat (limited to 'lisp')
| -rw-r--r-- | lisp/net/tramp-adb.el | 69 | ||||
| -rw-r--r-- | lisp/net/tramp-gvfs.el | 7 | ||||
| -rw-r--r-- | lisp/net/tramp-sh.el | 174 |
3 files changed, 133 insertions, 117 deletions
diff --git a/lisp/net/tramp-adb.el b/lisp/net/tramp-adb.el index e75efcf483f..bf21db2e8d8 100644 --- a/lisp/net/tramp-adb.el +++ b/lisp/net/tramp-adb.el | |||
| @@ -802,38 +802,43 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored." | |||
| 802 | (setq filename (expand-file-name filename) | 802 | (setq filename (expand-file-name filename) |
| 803 | newname (expand-file-name newname)) | 803 | newname (expand-file-name newname)) |
| 804 | 804 | ||
| 805 | (let ((t1 (tramp-tramp-file-p filename)) | 805 | (if (file-directory-p filename) |
| 806 | (t2 (tramp-tramp-file-p newname))) | 806 | (progn |
| 807 | (with-parsed-tramp-file-name (if t1 filename newname) nil | 807 | (copy-directory filename newname t t) |
| 808 | (with-tramp-progress-reporter | 808 | (delete-directory filename 'recursive)) |
| 809 | v 0 (format "Renaming %s to %s" filename newname) | 809 | |
| 810 | 810 | (let ((t1 (tramp-tramp-file-p filename)) | |
| 811 | (if (and t1 t2 | 811 | (t2 (tramp-tramp-file-p newname))) |
| 812 | (tramp-equal-remote filename newname) | 812 | (with-parsed-tramp-file-name (if t1 filename newname) nil |
| 813 | (not (file-directory-p filename))) | 813 | (with-tramp-progress-reporter |
| 814 | (let ((l1 (file-remote-p filename 'localname)) | 814 | v 0 (format "Renaming %s to %s" filename newname) |
| 815 | (l2 (file-remote-p newname 'localname))) | 815 | |
| 816 | (when (and (not ok-if-already-exists) | 816 | (if (and t1 t2 |
| 817 | (file-exists-p newname)) | 817 | (tramp-equal-remote filename newname) |
| 818 | (tramp-error v 'file-already-exists newname)) | 818 | (not (file-directory-p filename))) |
| 819 | ;; We must also flush the cache of the directory, because | 819 | (let ((l1 (file-remote-p filename 'localname)) |
| 820 | ;; `file-attributes' reads the values from there. | 820 | (l2 (file-remote-p newname 'localname))) |
| 821 | (tramp-flush-file-property v (file-name-directory l1)) | 821 | (when (and (not ok-if-already-exists) |
| 822 | (tramp-flush-file-property v l1) | 822 | (file-exists-p newname)) |
| 823 | (tramp-flush-file-property v (file-name-directory l2)) | 823 | (tramp-error v 'file-already-exists newname)) |
| 824 | (tramp-flush-file-property v l2) | 824 | ;; We must also flush the cache of the directory, because |
| 825 | ;; Short track. | 825 | ;; `file-attributes' reads the values from there. |
| 826 | (tramp-adb-barf-unless-okay | 826 | (tramp-flush-file-property v (file-name-directory l1)) |
| 827 | v (format | 827 | (tramp-flush-file-property v l1) |
| 828 | "mv -f %s %s" | 828 | (tramp-flush-file-property v (file-name-directory l2)) |
| 829 | (tramp-shell-quote-argument l1) | 829 | (tramp-flush-file-property v l2) |
| 830 | (tramp-shell-quote-argument l2)) | 830 | ;; Short track. |
| 831 | "Error renaming %s to %s" filename newname)) | 831 | (tramp-adb-barf-unless-okay |
| 832 | 832 | v (format | |
| 833 | ;; Rename by copy. | 833 | "mv -f %s %s" |
| 834 | (copy-file | 834 | (tramp-shell-quote-argument l1) |
| 835 | filename newname ok-if-already-exists 'keep-time 'preserve-uid-gid) | 835 | (tramp-shell-quote-argument l2)) |
| 836 | (delete-file filename)))))) | 836 | "Error renaming %s to %s" filename newname)) |
| 837 | |||
| 838 | ;; Rename by copy. | ||
| 839 | (copy-file | ||
| 840 | filename newname ok-if-already-exists 'keep-time 'preserve-uid-gid) | ||
| 841 | (delete-file filename))))))) | ||
| 837 | 842 | ||
| 838 | (defun tramp-adb-handle-process-file | 843 | (defun tramp-adb-handle-process-file |
| 839 | (program &optional infile destination display &rest args) | 844 | (program &optional infile destination display &rest args) |
diff --git a/lisp/net/tramp-gvfs.el b/lisp/net/tramp-gvfs.el index 2b29a1b55f5..51d24cbc1b0 100644 --- a/lisp/net/tramp-gvfs.el +++ b/lisp/net/tramp-gvfs.el | |||
| @@ -675,6 +675,11 @@ file names." | |||
| 675 | (unless (memq op '(copy rename)) | 675 | (unless (memq op '(copy rename)) |
| 676 | (error "Unknown operation `%s', must be `copy' or `rename'" op)) | 676 | (error "Unknown operation `%s', must be `copy' or `rename'" op)) |
| 677 | 677 | ||
| 678 | (if (file-directory-p filename) | ||
| 679 | (progn | ||
| 680 | (copy-directory filename newname keep-date t) | ||
| 681 | (when (eq op 'rename) (delete-directory filename 'recursive))) | ||
| 682 | |||
| 678 | (let ((t1 (tramp-tramp-file-p filename)) | 683 | (let ((t1 (tramp-tramp-file-p filename)) |
| 679 | (t2 (tramp-tramp-file-p newname)) | 684 | (t2 (tramp-tramp-file-p newname)) |
| 680 | (equal-remote (tramp-equal-remote filename newname)) | 685 | (equal-remote (tramp-equal-remote filename newname)) |
| @@ -738,7 +743,7 @@ file names." | |||
| 738 | (when t2 | 743 | (when t2 |
| 739 | (with-parsed-tramp-file-name newname nil | 744 | (with-parsed-tramp-file-name newname nil |
| 740 | (tramp-flush-file-property v (file-name-directory localname)) | 745 | (tramp-flush-file-property v (file-name-directory localname)) |
| 741 | (tramp-flush-file-property v localname))))))) | 746 | (tramp-flush-file-property v localname)))))))) |
| 742 | 747 | ||
| 743 | (defun tramp-gvfs-handle-copy-file | 748 | (defun tramp-gvfs-handle-copy-file |
| 744 | (filename newname &optional ok-if-already-exists keep-date | 749 | (filename newname &optional ok-if-already-exists keep-date |
diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el index bdb7a132408..52a6b8fac0b 100644 --- a/lisp/net/tramp-sh.el +++ b/lisp/net/tramp-sh.el | |||
| @@ -2039,96 +2039,102 @@ of `copy' and `rename'. FILENAME and NEWNAME must be absolute | |||
| 2039 | file names." | 2039 | file names." |
| 2040 | (unless (memq op '(copy rename)) | 2040 | (unless (memq op '(copy rename)) |
| 2041 | (error "Unknown operation `%s', must be `copy' or `rename'" op)) | 2041 | (error "Unknown operation `%s', must be `copy' or `rename'" op)) |
| 2042 | (let ((t1 (tramp-tramp-file-p filename)) | ||
| 2043 | (t2 (tramp-tramp-file-p newname)) | ||
| 2044 | (length (tramp-compat-file-attribute-size | ||
| 2045 | (file-attributes (file-truename filename)))) | ||
| 2046 | (attributes (and preserve-extended-attributes | ||
| 2047 | (apply 'file-extended-attributes (list filename))))) | ||
| 2048 | 2042 | ||
| 2049 | (with-parsed-tramp-file-name (if t1 filename newname) nil | 2043 | (if (file-directory-p filename) |
| 2050 | (when (and (not ok-if-already-exists) (file-exists-p newname)) | 2044 | (progn |
| 2051 | (tramp-error v 'file-already-exists newname)) | 2045 | (copy-directory filename newname keep-date t) |
| 2052 | 2046 | (when (eq op 'rename) (delete-directory filename 'recursive))) | |
| 2053 | (with-tramp-progress-reporter | ||
| 2054 | v 0 (format "%s %s to %s" | ||
| 2055 | (if (eq op 'copy) "Copying" "Renaming") | ||
| 2056 | filename newname) | ||
| 2057 | 2047 | ||
| 2058 | (cond | 2048 | (let ((t1 (tramp-tramp-file-p filename)) |
| 2059 | ;; Both are Tramp files. | 2049 | (t2 (tramp-tramp-file-p newname)) |
| 2060 | ((and t1 t2) | 2050 | (length (tramp-compat-file-attribute-size |
| 2061 | (with-parsed-tramp-file-name filename v1 | 2051 | (file-attributes (file-truename filename)))) |
| 2062 | (with-parsed-tramp-file-name newname v2 | 2052 | (attributes (and preserve-extended-attributes |
| 2063 | (cond | 2053 | (apply 'file-extended-attributes (list filename))))) |
| 2064 | ;; Shortcut: if method, host, user are the same for | ||
| 2065 | ;; both files, we invoke `cp' or `mv' on the remote | ||
| 2066 | ;; host directly. | ||
| 2067 | ((tramp-equal-remote filename newname) | ||
| 2068 | (tramp-do-copy-or-rename-file-directly | ||
| 2069 | op filename newname | ||
| 2070 | ok-if-already-exists keep-date preserve-uid-gid)) | ||
| 2071 | |||
| 2072 | ;; Try out-of-band operation. | ||
| 2073 | ((and | ||
| 2074 | (tramp-method-out-of-band-p v1 length) | ||
| 2075 | (tramp-method-out-of-band-p v2 length)) | ||
| 2076 | (tramp-do-copy-or-rename-file-out-of-band | ||
| 2077 | op filename newname keep-date)) | ||
| 2078 | |||
| 2079 | ;; No shortcut was possible. So we copy the file | ||
| 2080 | ;; first. If the operation was `rename', we go back | ||
| 2081 | ;; and delete the original file (if the copy was | ||
| 2082 | ;; successful). The approach is simple-minded: we | ||
| 2083 | ;; create a new buffer, insert the contents of the | ||
| 2084 | ;; source file into it, then write out the buffer to | ||
| 2085 | ;; the target file. The advantage is that it doesn't | ||
| 2086 | ;; matter which file name handlers are used for the | ||
| 2087 | ;; source and target file. | ||
| 2088 | (t | ||
| 2089 | (tramp-do-copy-or-rename-file-via-buffer | ||
| 2090 | op filename newname keep-date)))))) | ||
| 2091 | |||
| 2092 | ;; One file is a Tramp file, the other one is local. | ||
| 2093 | ((or t1 t2) | ||
| 2094 | (cond | ||
| 2095 | ;; Fast track on local machine. | ||
| 2096 | ((tramp-local-host-p v) | ||
| 2097 | (tramp-do-copy-or-rename-file-directly | ||
| 2098 | op filename newname | ||
| 2099 | ok-if-already-exists keep-date preserve-uid-gid)) | ||
| 2100 | 2054 | ||
| 2101 | ;; If the Tramp file has an out-of-band method, the | 2055 | (with-parsed-tramp-file-name (if t1 filename newname) nil |
| 2102 | ;; corresponding copy-program can be invoked. | 2056 | (when (and (not ok-if-already-exists) (file-exists-p newname)) |
| 2103 | ((tramp-method-out-of-band-p v length) | 2057 | (tramp-error v 'file-already-exists newname)) |
| 2104 | (tramp-do-copy-or-rename-file-out-of-band | ||
| 2105 | op filename newname keep-date)) | ||
| 2106 | 2058 | ||
| 2107 | ;; Use the inline method via a Tramp buffer. | 2059 | (with-tramp-progress-reporter |
| 2108 | (t (tramp-do-copy-or-rename-file-via-buffer | 2060 | v 0 (format "%s %s to %s" |
| 2109 | op filename newname keep-date)))) | 2061 | (if (eq op 'copy) "Copying" "Renaming") |
| 2062 | filename newname) | ||
| 2110 | 2063 | ||
| 2111 | (t | 2064 | (cond |
| 2112 | ;; One of them must be a Tramp file. | 2065 | ;; Both are Tramp files. |
| 2113 | (error "Tramp implementation says this cannot happen"))) | 2066 | ((and t1 t2) |
| 2067 | (with-parsed-tramp-file-name filename v1 | ||
| 2068 | (with-parsed-tramp-file-name newname v2 | ||
| 2069 | (cond | ||
| 2070 | ;; Shortcut: if method, host, user are the same for | ||
| 2071 | ;; both files, we invoke `cp' or `mv' on the remote | ||
| 2072 | ;; host directly. | ||
| 2073 | ((tramp-equal-remote filename newname) | ||
| 2074 | (tramp-do-copy-or-rename-file-directly | ||
| 2075 | op filename newname | ||
| 2076 | ok-if-already-exists keep-date preserve-uid-gid)) | ||
| 2077 | |||
| 2078 | ;; Try out-of-band operation. | ||
| 2079 | ((and | ||
| 2080 | (tramp-method-out-of-band-p v1 length) | ||
| 2081 | (tramp-method-out-of-band-p v2 length)) | ||
| 2082 | (tramp-do-copy-or-rename-file-out-of-band | ||
| 2083 | op filename newname keep-date)) | ||
| 2084 | |||
| 2085 | ;; No shortcut was possible. So we copy the file | ||
| 2086 | ;; first. If the operation was `rename', we go back | ||
| 2087 | ;; and delete the original file (if the copy was | ||
| 2088 | ;; successful). The approach is simple-minded: we | ||
| 2089 | ;; create a new buffer, insert the contents of the | ||
| 2090 | ;; source file into it, then write out the buffer to | ||
| 2091 | ;; the target file. The advantage is that it doesn't | ||
| 2092 | ;; matter which file name handlers are used for the | ||
| 2093 | ;; source and target file. | ||
| 2094 | (t | ||
| 2095 | (tramp-do-copy-or-rename-file-via-buffer | ||
| 2096 | op filename newname keep-date)))))) | ||
| 2097 | |||
| 2098 | ;; One file is a Tramp file, the other one is local. | ||
| 2099 | ((or t1 t2) | ||
| 2100 | (cond | ||
| 2101 | ;; Fast track on local machine. | ||
| 2102 | ((tramp-local-host-p v) | ||
| 2103 | (tramp-do-copy-or-rename-file-directly | ||
| 2104 | op filename newname | ||
| 2105 | ok-if-already-exists keep-date preserve-uid-gid)) | ||
| 2106 | |||
| 2107 | ;; If the Tramp file has an out-of-band method, the | ||
| 2108 | ;; corresponding copy-program can be invoked. | ||
| 2109 | ((tramp-method-out-of-band-p v length) | ||
| 2110 | (tramp-do-copy-or-rename-file-out-of-band | ||
| 2111 | op filename newname keep-date)) | ||
| 2112 | |||
| 2113 | ;; Use the inline method via a Tramp buffer. | ||
| 2114 | (t (tramp-do-copy-or-rename-file-via-buffer | ||
| 2115 | op filename newname keep-date)))) | ||
| 2114 | 2116 | ||
| 2115 | ;; Handle `preserve-extended-attributes'. We ignore possible | 2117 | (t |
| 2116 | ;; errors, because ACL strings could be incompatible. | 2118 | ;; One of them must be a Tramp file. |
| 2117 | (when attributes | 2119 | (error "Tramp implementation says this cannot happen"))) |
| 2118 | (ignore-errors | 2120 | |
| 2119 | (apply 'set-file-extended-attributes (list newname attributes)))) | 2121 | ;; Handle `preserve-extended-attributes'. We ignore possible |
| 2120 | 2122 | ;; errors, because ACL strings could be incompatible. | |
| 2121 | ;; In case of `rename', we must flush the cache of the source file. | 2123 | (when attributes |
| 2122 | (when (and t1 (eq op 'rename)) | 2124 | (ignore-errors |
| 2123 | (with-parsed-tramp-file-name filename v1 | 2125 | (apply 'set-file-extended-attributes (list newname attributes)))) |
| 2124 | (tramp-flush-file-property v1 (file-name-directory v1-localname)) | 2126 | |
| 2125 | (tramp-flush-file-property v1 v1-localname))) | 2127 | ;; In case of `rename', we must flush the cache of the source file. |
| 2126 | 2128 | (when (and t1 (eq op 'rename)) | |
| 2127 | ;; When newname did exist, we have wrong cached values. | 2129 | (with-parsed-tramp-file-name filename v1 |
| 2128 | (when t2 | 2130 | (tramp-flush-file-property v1 (file-name-directory v1-localname)) |
| 2129 | (with-parsed-tramp-file-name newname v2 | 2131 | (tramp-flush-file-property v1 v1-localname))) |
| 2130 | (tramp-flush-file-property v2 (file-name-directory v2-localname)) | 2132 | |
| 2131 | (tramp-flush-file-property v2 v2-localname))))))) | 2133 | ;; When newname did exist, we have wrong cached values. |
| 2134 | (when t2 | ||
| 2135 | (with-parsed-tramp-file-name newname v2 | ||
| 2136 | (tramp-flush-file-property v2 (file-name-directory v2-localname)) | ||
| 2137 | (tramp-flush-file-property v2 v2-localname)))))))) | ||
| 2132 | 2138 | ||
| 2133 | (defun tramp-do-copy-or-rename-file-via-buffer (op filename newname keep-date) | 2139 | (defun tramp-do-copy-or-rename-file-via-buffer (op filename newname keep-date) |
| 2134 | "Use an Emacs buffer to copy or rename a file. | 2140 | "Use an Emacs buffer to copy or rename a file. |