aboutsummaryrefslogtreecommitdiffstats
path: root/lisp
diff options
context:
space:
mode:
authorMichael Albinus2017-10-20 12:46:54 +0200
committerMichael Albinus2017-10-20 12:46:54 +0200
commitb500e06f4d05dc094b79f8f2c063e070a5a3306e (patch)
treee0d6131de893be18d6217f7709a40a5bedd2c72d /lisp
parentd815de017bb531fed751ee0515ed90b73d7a9936 (diff)
downloademacs-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.el69
-rw-r--r--lisp/net/tramp-gvfs.el7
-rw-r--r--lisp/net/tramp-sh.el174
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
2039file names." 2039file 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.