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.
This commit is contained in:
Michael Albinus 2017-10-20 12:46:54 +02:00
parent d815de017b
commit b500e06f4d
4 changed files with 304 additions and 292 deletions

View file

@ -802,38 +802,43 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored."
(setq filename (expand-file-name filename) (setq filename (expand-file-name filename)
newname (expand-file-name newname)) newname (expand-file-name newname))
(let ((t1 (tramp-tramp-file-p filename)) (if (file-directory-p filename)
(t2 (tramp-tramp-file-p newname))) (progn
(with-parsed-tramp-file-name (if t1 filename newname) nil (copy-directory filename newname t t)
(with-tramp-progress-reporter (delete-directory filename 'recursive))
v 0 (format "Renaming %s to %s" filename newname)
(if (and t1 t2 (let ((t1 (tramp-tramp-file-p filename))
(tramp-equal-remote filename newname) (t2 (tramp-tramp-file-p newname)))
(not (file-directory-p filename))) (with-parsed-tramp-file-name (if t1 filename newname) nil
(let ((l1 (file-remote-p filename 'localname)) (with-tramp-progress-reporter
(l2 (file-remote-p newname 'localname))) v 0 (format "Renaming %s to %s" filename newname)
(when (and (not ok-if-already-exists)
(file-exists-p newname))
(tramp-error v 'file-already-exists newname))
;; We must also flush the cache of the directory, because
;; `file-attributes' reads the values from there.
(tramp-flush-file-property v (file-name-directory l1))
(tramp-flush-file-property v l1)
(tramp-flush-file-property v (file-name-directory l2))
(tramp-flush-file-property v l2)
;; Short track.
(tramp-adb-barf-unless-okay
v (format
"mv -f %s %s"
(tramp-shell-quote-argument l1)
(tramp-shell-quote-argument l2))
"Error renaming %s to %s" filename newname))
;; Rename by copy. (if (and t1 t2
(copy-file (tramp-equal-remote filename newname)
filename newname ok-if-already-exists 'keep-time 'preserve-uid-gid) (not (file-directory-p filename)))
(delete-file filename)))))) (let ((l1 (file-remote-p filename 'localname))
(l2 (file-remote-p newname 'localname)))
(when (and (not ok-if-already-exists)
(file-exists-p newname))
(tramp-error v 'file-already-exists newname))
;; We must also flush the cache of the directory, because
;; `file-attributes' reads the values from there.
(tramp-flush-file-property v (file-name-directory l1))
(tramp-flush-file-property v l1)
(tramp-flush-file-property v (file-name-directory l2))
(tramp-flush-file-property v l2)
;; Short track.
(tramp-adb-barf-unless-okay
v (format
"mv -f %s %s"
(tramp-shell-quote-argument l1)
(tramp-shell-quote-argument l2))
"Error renaming %s to %s" filename newname))
;; Rename by copy.
(copy-file
filename newname ok-if-already-exists 'keep-time 'preserve-uid-gid)
(delete-file filename)))))))
(defun tramp-adb-handle-process-file (defun tramp-adb-handle-process-file
(program &optional infile destination display &rest args) (program &optional infile destination display &rest args)

View file

@ -675,6 +675,11 @@ file names."
(unless (memq op '(copy rename)) (unless (memq op '(copy rename))
(error "Unknown operation `%s', must be `copy' or `rename'" op)) (error "Unknown operation `%s', must be `copy' or `rename'" op))
(if (file-directory-p filename)
(progn
(copy-directory filename newname keep-date t)
(when (eq op 'rename) (delete-directory filename 'recursive)))
(let ((t1 (tramp-tramp-file-p filename)) (let ((t1 (tramp-tramp-file-p filename))
(t2 (tramp-tramp-file-p newname)) (t2 (tramp-tramp-file-p newname))
(equal-remote (tramp-equal-remote filename newname)) (equal-remote (tramp-equal-remote filename newname))
@ -738,7 +743,7 @@ file names."
(when t2 (when t2
(with-parsed-tramp-file-name newname nil (with-parsed-tramp-file-name newname nil
(tramp-flush-file-property v (file-name-directory localname)) (tramp-flush-file-property v (file-name-directory localname))
(tramp-flush-file-property v localname))))))) (tramp-flush-file-property v localname))))))))
(defun tramp-gvfs-handle-copy-file (defun tramp-gvfs-handle-copy-file
(filename newname &optional ok-if-already-exists keep-date (filename newname &optional ok-if-already-exists keep-date

View file

@ -2039,96 +2039,102 @@ of `copy' and `rename'. FILENAME and NEWNAME must be absolute
file names." file names."
(unless (memq op '(copy rename)) (unless (memq op '(copy rename))
(error "Unknown operation `%s', must be `copy' or `rename'" op)) (error "Unknown operation `%s', must be `copy' or `rename'" op))
(let ((t1 (tramp-tramp-file-p filename))
(t2 (tramp-tramp-file-p newname))
(length (tramp-compat-file-attribute-size
(file-attributes (file-truename filename))))
(attributes (and preserve-extended-attributes
(apply 'file-extended-attributes (list filename)))))
(with-parsed-tramp-file-name (if t1 filename newname) nil (if (file-directory-p filename)
(when (and (not ok-if-already-exists) (file-exists-p newname)) (progn
(tramp-error v 'file-already-exists newname)) (copy-directory filename newname keep-date t)
(when (eq op 'rename) (delete-directory filename 'recursive)))
(with-tramp-progress-reporter (let ((t1 (tramp-tramp-file-p filename))
v 0 (format "%s %s to %s" (t2 (tramp-tramp-file-p newname))
(if (eq op 'copy) "Copying" "Renaming") (length (tramp-compat-file-attribute-size
filename newname) (file-attributes (file-truename filename))))
(attributes (and preserve-extended-attributes
(apply 'file-extended-attributes (list filename)))))
(cond (with-parsed-tramp-file-name (if t1 filename newname) nil
;; Both are Tramp files. (when (and (not ok-if-already-exists) (file-exists-p newname))
((and t1 t2) (tramp-error v 'file-already-exists newname))
(with-parsed-tramp-file-name filename v1
(with-parsed-tramp-file-name newname v2
(cond
;; Shortcut: if method, host, user are the same for
;; both files, we invoke `cp' or `mv' on the remote
;; host directly.
((tramp-equal-remote filename newname)
(tramp-do-copy-or-rename-file-directly
op filename newname
ok-if-already-exists keep-date preserve-uid-gid))
;; Try out-of-band operation. (with-tramp-progress-reporter
((and v 0 (format "%s %s to %s"
(tramp-method-out-of-band-p v1 length) (if (eq op 'copy) "Copying" "Renaming")
(tramp-method-out-of-band-p v2 length)) filename newname)
(tramp-do-copy-or-rename-file-out-of-band
op filename newname keep-date))
;; No shortcut was possible. So we copy the file
;; first. If the operation was `rename', we go back
;; and delete the original file (if the copy was
;; successful). The approach is simple-minded: we
;; create a new buffer, insert the contents of the
;; source file into it, then write out the buffer to
;; the target file. The advantage is that it doesn't
;; matter which file name handlers are used for the
;; source and target file.
(t
(tramp-do-copy-or-rename-file-via-buffer
op filename newname keep-date))))))
;; One file is a Tramp file, the other one is local.
((or t1 t2)
(cond (cond
;; Fast track on local machine. ;; Both are Tramp files.
((tramp-local-host-p v) ((and t1 t2)
(tramp-do-copy-or-rename-file-directly (with-parsed-tramp-file-name filename v1
op filename newname (with-parsed-tramp-file-name newname v2
ok-if-already-exists keep-date preserve-uid-gid)) (cond
;; Shortcut: if method, host, user are the same for
;; both files, we invoke `cp' or `mv' on the remote
;; host directly.
((tramp-equal-remote filename newname)
(tramp-do-copy-or-rename-file-directly
op filename newname
ok-if-already-exists keep-date preserve-uid-gid))
;; If the Tramp file has an out-of-band method, the ;; Try out-of-band operation.
;; corresponding copy-program can be invoked. ((and
((tramp-method-out-of-band-p v length) (tramp-method-out-of-band-p v1 length)
(tramp-do-copy-or-rename-file-out-of-band (tramp-method-out-of-band-p v2 length))
op filename newname keep-date)) (tramp-do-copy-or-rename-file-out-of-band
op filename newname keep-date))
;; Use the inline method via a Tramp buffer. ;; No shortcut was possible. So we copy the file
(t (tramp-do-copy-or-rename-file-via-buffer ;; first. If the operation was `rename', we go back
op filename newname keep-date)))) ;; and delete the original file (if the copy was
;; successful). The approach is simple-minded: we
;; create a new buffer, insert the contents of the
;; source file into it, then write out the buffer to
;; the target file. The advantage is that it doesn't
;; matter which file name handlers are used for the
;; source and target file.
(t
(tramp-do-copy-or-rename-file-via-buffer
op filename newname keep-date))))))
(t ;; One file is a Tramp file, the other one is local.
;; One of them must be a Tramp file. ((or t1 t2)
(error "Tramp implementation says this cannot happen"))) (cond
;; Fast track on local machine.
((tramp-local-host-p v)
(tramp-do-copy-or-rename-file-directly
op filename newname
ok-if-already-exists keep-date preserve-uid-gid))
;; Handle `preserve-extended-attributes'. We ignore possible ;; If the Tramp file has an out-of-band method, the
;; errors, because ACL strings could be incompatible. ;; corresponding copy-program can be invoked.
(when attributes ((tramp-method-out-of-band-p v length)
(ignore-errors (tramp-do-copy-or-rename-file-out-of-band
(apply 'set-file-extended-attributes (list newname attributes)))) op filename newname keep-date))
;; In case of `rename', we must flush the cache of the source file. ;; Use the inline method via a Tramp buffer.
(when (and t1 (eq op 'rename)) (t (tramp-do-copy-or-rename-file-via-buffer
(with-parsed-tramp-file-name filename v1 op filename newname keep-date))))
(tramp-flush-file-property v1 (file-name-directory v1-localname))
(tramp-flush-file-property v1 v1-localname)))
;; When newname did exist, we have wrong cached values. (t
(when t2 ;; One of them must be a Tramp file.
(with-parsed-tramp-file-name newname v2 (error "Tramp implementation says this cannot happen")))
(tramp-flush-file-property v2 (file-name-directory v2-localname))
(tramp-flush-file-property v2 v2-localname))))))) ;; Handle `preserve-extended-attributes'. We ignore possible
;; errors, because ACL strings could be incompatible.
(when attributes
(ignore-errors
(apply 'set-file-extended-attributes (list newname attributes))))
;; In case of `rename', we must flush the cache of the source file.
(when (and t1 (eq op 'rename))
(with-parsed-tramp-file-name filename v1
(tramp-flush-file-property v1 (file-name-directory v1-localname))
(tramp-flush-file-property v1 v1-localname)))
;; When newname did exist, we have wrong cached values.
(when t2
(with-parsed-tramp-file-name newname v2
(tramp-flush-file-property v2 (file-name-directory v2-localname))
(tramp-flush-file-property v2 v2-localname))))))))
(defun tramp-do-copy-or-rename-file-via-buffer (op filename newname keep-date) (defun tramp-do-copy-or-rename-file-via-buffer (op filename newname keep-date)
"Use an Emacs buffer to copy or rename a file. "Use an Emacs buffer to copy or rename a file.

View file

@ -1883,96 +1883,98 @@ This checks also `file-name-as-directory', `file-name-directory',
(let (quoted) (let (quoted)
(let ((tmp-name1 (tramp--test-make-temp-name nil quoted)) (let ((tmp-name1 (tramp--test-make-temp-name nil quoted))
(tmp-name2 (tramp--test-make-temp-name nil quoted)) (tmp-name2 (tramp--test-make-temp-name nil quoted))
(tmp-name3 (tramp--test-make-temp-name nil quoted)) (tmp-name3 (tramp--test-make-temp-name 'local quoted)))
(tmp-name4 (tramp--test-make-temp-name 'local quoted)) (dolist (source-target
(tmp-name5 (tramp--test-make-temp-name 'local quoted))) `(;; Copy on remote side.
(,tmp-name1 . ,tmp-name2)
;; Copy from remote side to local side.
(,tmp-name1 . ,tmp-name3)
;; Copy from local side to remote side.
(,tmp-name3 . ,tmp-name1)))
(let ((source (car source-target))
(target (cdr source-target)))
;; Copy on remote side. ;; Copy simple file.
(unwind-protect (unwind-protect
(progn (progn
(write-region "foo" nil tmp-name1) (write-region "foo" nil source)
(copy-file tmp-name1 tmp-name2) (should (file-exists-p source))
(should (file-exists-p tmp-name2)) (copy-file source target)
(with-temp-buffer (should (file-exists-p target))
(insert-file-contents tmp-name2) (with-temp-buffer
(should (string-equal (buffer-string) "foo"))) (insert-file-contents target)
(should-error (should (string-equal (buffer-string) "foo")))
(copy-file tmp-name1 tmp-name2) (should-error
:type 'file-already-exists) (copy-file source target)
(copy-file tmp-name1 tmp-name2 'ok) :type 'file-already-exists)
(make-directory tmp-name3) (copy-file source target 'ok))
;; This has been changed in Emacs 26.1.
(when (tramp--test-emacs26-p)
(should-error
(copy-file tmp-name1 tmp-name3)
:type 'file-already-exists))
(copy-file tmp-name1 (file-name-as-directory tmp-name3))
(should
(file-exists-p
(expand-file-name (file-name-nondirectory tmp-name1) tmp-name3))))
;; Cleanup. ;; Cleanup.
(ignore-errors (delete-file tmp-name1)) (ignore-errors (delete-file source))
(ignore-errors (delete-file tmp-name2)) (ignore-errors (delete-file target)))
(ignore-errors (delete-directory tmp-name3 'recursive)))
;; Copy from remote side to local side. ;; Copy file to directory.
(unwind-protect (unwind-protect
(progn (progn
(write-region "foo" nil tmp-name1) (write-region "foo" nil source)
(copy-file tmp-name1 tmp-name4) (should (file-exists-p source))
(should (file-exists-p tmp-name4)) (make-directory target)
(with-temp-buffer (should (file-directory-p target))
(insert-file-contents tmp-name4) ;; This has been changed in Emacs 26.1.
(should (string-equal (buffer-string) "foo"))) (when (tramp--test-emacs26-p)
(should-error (should-error
(copy-file tmp-name1 tmp-name4) (copy-file source target)
:type 'file-already-exists) :type 'file-already-exists))
(copy-file tmp-name1 tmp-name4 'ok) (copy-file source (file-name-as-directory target))
(make-directory tmp-name5) (should
;; This has been changed in Emacs 26.1. (file-exists-p
(when (tramp--test-emacs26-p) (expand-file-name (file-name-nondirectory source) target))))
(should-error
(copy-file tmp-name1 tmp-name5)
:type 'file-already-exists))
(copy-file tmp-name1 (file-name-as-directory tmp-name5))
(should
(file-exists-p
(expand-file-name (file-name-nondirectory tmp-name1) tmp-name5))))
;; Cleanup. ;; Cleanup.
(ignore-errors (delete-file tmp-name1)) (ignore-errors (delete-file source))
(ignore-errors (delete-file tmp-name4)) (ignore-errors (delete-directory target 'recursive)))
(ignore-errors (delete-directory tmp-name5 'recursive)))
;; Copy from local side to remote side. ;; Copy directory to existing directory.
(unwind-protect (unwind-protect
(progn (progn
(write-region "foo" nil tmp-name4 nil 'nomessage) (make-directory source)
(copy-file tmp-name4 tmp-name1) (should (file-directory-p source))
(should (file-exists-p tmp-name1)) (write-region "foo" nil (expand-file-name "foo" source))
(with-temp-buffer (should (file-exists-p (expand-file-name "foo" source)))
(insert-file-contents tmp-name1) (make-directory target)
(should (string-equal (buffer-string) "foo"))) (should (file-directory-p target))
(should-error ;; Directory `target' exists already, so we must use
(copy-file tmp-name4 tmp-name1) ;; `file-name-as-directory'.
:type 'file-already-exists) (copy-file source (file-name-as-directory target))
(copy-file tmp-name4 tmp-name1 'ok) (should
(make-directory tmp-name3) (file-exists-p
;; This has been changed in Emacs 26.1. (expand-file-name
(when (tramp--test-emacs26-p) (concat (file-name-nondirectory source) "/foo") target))))
(should-error
(copy-file tmp-name4 tmp-name3)
:type 'file-already-exists))
(copy-file tmp-name4 (file-name-as-directory tmp-name3))
(should
(file-exists-p
(expand-file-name (file-name-nondirectory tmp-name4) tmp-name3))))
;; Cleanup. ;; Cleanup.
(ignore-errors (delete-file tmp-name1)) (ignore-errors (delete-directory source 'recursive))
(ignore-errors (delete-file tmp-name4)) (ignore-errors (delete-directory target 'recursive)))
(ignore-errors (delete-directory tmp-name3 'recursive))))))
;; Copy directory/file to non-existing directory.
(unwind-protect
(progn
(make-directory source)
(should (file-directory-p source))
(write-region "foo" nil (expand-file-name "foo" source))
(should (file-exists-p (expand-file-name "foo" source)))
(make-directory target)
(should (file-directory-p target))
(copy-file
source
(expand-file-name (file-name-nondirectory source) target))
(should
(file-exists-p
(expand-file-name
(concat (file-name-nondirectory source) "/foo") target))))
;; Cleanup.
(ignore-errors (delete-directory source 'recursive))
(ignore-errors (delete-directory target 'recursive))))))))
(ert-deftest tramp-test12-rename-file () (ert-deftest tramp-test12-rename-file ()
"Check `rename-file'." "Check `rename-file'."
@ -1983,111 +1985,105 @@ This checks also `file-name-as-directory', `file-name-directory',
(let (quoted) (let (quoted)
(let ((tmp-name1 (tramp--test-make-temp-name nil quoted)) (let ((tmp-name1 (tramp--test-make-temp-name nil quoted))
(tmp-name2 (tramp--test-make-temp-name nil quoted)) (tmp-name2 (tramp--test-make-temp-name nil quoted))
(tmp-name3 (tramp--test-make-temp-name nil quoted)) (tmp-name3 (tramp--test-make-temp-name 'local quoted)))
(tmp-name4 (tramp--test-make-temp-name 'local quoted)) (dolist (source-target
(tmp-name5 (tramp--test-make-temp-name 'local quoted))) `(;; Rename on remote side.
(,tmp-name1 . ,tmp-name2)
;; Rename from remote side to local side.
(,tmp-name1 . ,tmp-name3)
;; Rename from local side to remote side.
(,tmp-name3 . ,tmp-name1)))
(let ((source (car source-target))
(target (cdr source-target)))
;; Rename on remote side. ;; Rename simple file.
(unwind-protect (unwind-protect
(progn (progn
(write-region "foo" nil tmp-name1) (write-region "foo" nil source)
(rename-file tmp-name1 tmp-name2) (should (file-exists-p source))
(should-not (file-exists-p tmp-name1)) (rename-file source target)
(should (file-exists-p tmp-name2)) (should-not (file-exists-p source))
(with-temp-buffer (should (file-exists-p target))
(insert-file-contents tmp-name2) (with-temp-buffer
(should (string-equal (buffer-string) "foo"))) (insert-file-contents target)
(write-region "foo" nil tmp-name1) (should (string-equal (buffer-string) "foo")))
(should-error (write-region "foo" nil source)
(rename-file tmp-name1 tmp-name2) (should (file-exists-p source))
:type 'file-already-exists) (should-error
(rename-file tmp-name1 tmp-name2 'ok) (rename-file source target)
(should-not (file-exists-p tmp-name1)) :type 'file-already-exists)
(write-region "foo" nil tmp-name1) (rename-file source target 'ok)
(make-directory tmp-name3) (should-not (file-exists-p source)))
;; This has been changed in Emacs 26.1.
(when (tramp--test-emacs26-p)
(should-error
(rename-file tmp-name1 tmp-name3)
:type 'file-already-exists))
(rename-file tmp-name1 (file-name-as-directory tmp-name3))
(should-not (file-exists-p tmp-name1))
(should
(file-exists-p
(expand-file-name (file-name-nondirectory tmp-name1) tmp-name3))))
;; Cleanup. ;; Cleanup.
(ignore-errors (delete-file tmp-name1)) (ignore-errors (delete-file source))
(ignore-errors (delete-file tmp-name2)) (ignore-errors (delete-file target)))
(ignore-errors (delete-directory tmp-name3 'recursive)))
;; Rename from remote side to local side. ;; Rename file to directory.
(unwind-protect (unwind-protect
(progn (progn
(write-region "foo" nil tmp-name1) (write-region "foo" nil source)
(rename-file tmp-name1 tmp-name4) (should (file-exists-p source))
(should-not (file-exists-p tmp-name1)) (make-directory target)
(should (file-exists-p tmp-name4)) (should (file-directory-p target))
(with-temp-buffer ;; This has been changed in Emacs 26.1.
(insert-file-contents tmp-name4) (when (tramp--test-emacs26-p)
(should (string-equal (buffer-string) "foo"))) (should-error
(write-region "foo" nil tmp-name1) (rename-file source target)
(should-error :type 'file-already-exists))
(rename-file tmp-name1 tmp-name4) (rename-file source (file-name-as-directory target))
:type 'file-already-exists) (should-not (file-exists-p source))
(rename-file tmp-name1 tmp-name4 'ok) (should
(should-not (file-exists-p tmp-name1)) (file-exists-p
(write-region "foo" nil tmp-name1) (expand-file-name (file-name-nondirectory source) target))))
(make-directory tmp-name5)
;; This has been changed in Emacs 26.1.
(when (tramp--test-emacs26-p)
(should-error
(rename-file tmp-name1 tmp-name5)
:type 'file-already-exists))
(rename-file tmp-name1 (file-name-as-directory tmp-name5))
(should-not (file-exists-p tmp-name1))
(should
(file-exists-p
(expand-file-name (file-name-nondirectory tmp-name1) tmp-name5))))
;; Cleanup. ;; Cleanup.
(ignore-errors (delete-file tmp-name1)) (ignore-errors (delete-file source))
(ignore-errors (delete-file tmp-name4)) (ignore-errors (delete-directory target 'recursive)))
(ignore-errors (delete-directory tmp-name5 'recursive)))
;; Rename from local side to remote side. ;; Rename directory to existing directory.
(unwind-protect (unwind-protect
(progn (progn
(write-region "foo" nil tmp-name4 nil 'nomessage) (make-directory source)
(rename-file tmp-name4 tmp-name1) (should (file-directory-p source))
(should-not (file-exists-p tmp-name4)) (write-region "foo" nil (expand-file-name "foo" source))
(should (file-exists-p tmp-name1)) (should (file-exists-p (expand-file-name "foo" source)))
(with-temp-buffer (make-directory target)
(insert-file-contents tmp-name1) (should (file-directory-p target))
(should (string-equal (buffer-string) "foo"))) ;; Directory `target' exists already, so we must use
(write-region "foo" nil tmp-name4 nil 'nomessage) ;; `file-name-as-directory'.
(should-error (rename-file source (file-name-as-directory target))
(rename-file tmp-name4 tmp-name1) (should-not (file-exists-p source))
:type 'file-already-exists) (should
(rename-file tmp-name4 tmp-name1 'ok) (file-exists-p
(should-not (file-exists-p tmp-name4)) (expand-file-name
(write-region "foo" nil tmp-name4 nil 'nomessage) (concat (file-name-nondirectory source) "/foo") target))))
(make-directory tmp-name3)
;; This has been changed in Emacs 26.1.
(when (tramp--test-emacs26-p)
(should-error
(rename-file tmp-name4 tmp-name3)
:type 'file-already-exists))
(rename-file tmp-name4 (file-name-as-directory tmp-name3))
(should-not (file-exists-p tmp-name4))
(should
(file-exists-p
(expand-file-name (file-name-nondirectory tmp-name4) tmp-name3))))
;; Cleanup. ;; Cleanup.
(ignore-errors (delete-file tmp-name1)) (ignore-errors (delete-directory source 'recursive))
(ignore-errors (delete-file tmp-name4)) (ignore-errors (delete-directory target 'recursive)))
(ignore-errors (delete-directory tmp-name3 'recursive))))))
;; Rename directory/file to non-existing directory.
(unwind-protect
(progn
(make-directory source)
(should (file-directory-p source))
(write-region "foo" nil (expand-file-name "foo" source))
(should (file-exists-p (expand-file-name "foo" source)))
(make-directory target)
(should (file-directory-p target))
(rename-file
source
(expand-file-name (file-name-nondirectory source) target))
(should-not (file-exists-p source))
(should
(file-exists-p
(expand-file-name
(concat (file-name-nondirectory source) "/foo") target))))
;; Cleanup.
(ignore-errors (delete-directory source 'recursive))
(ignore-errors (delete-directory target 'recursive))))))))
(ert-deftest tramp-test13-make-directory () (ert-deftest tramp-test13-make-directory ()
"Check `make-directory'. "Check `make-directory'.