]> git.eshelyaron.com Git - emacs.git/commitdiff
Fix cross-filesystem directory trashing (Bug#58721)
authorMike Kupfer <mkupfer@alum.berkeley.edu>
Sun, 30 Oct 2022 17:31:11 +0000 (10:31 -0700)
committerEli Zaretskii <eliz@gnu.org>
Thu, 24 Nov 2022 11:16:48 +0000 (13:16 +0200)
* lisp/files.el (move-file-to-trash): When trashing a directory with
the same name as something that's already in the trash, copy it into
the trash folder and then delete it, rather than using rename-file.

lisp/files.el

index b947451369ca61b20ef104974d9895b36edab035..127cf77240f56f935f70468f6ebd926afd9cc33a 100644 (file)
@@ -8596,10 +8596,27 @@ Otherwise, trash FILENAME using the freedesktop.org conventions,
                    (setq files-base (substring (file-name-nondirectory info-fn)
                                                 0 (- (length ".trashinfo"))))
                    (write-region nil nil info-fn nil 'quiet info-fn)))
-                ;; Finally, try to move the file to the trashcan.
+                ;; Finally, try to move the item to the trashcan.  If
+                 ;; it's a file, just move it.  Things are more
+                 ;; complicated for directories.  If the target
+                 ;; directory already exists (due to uniquification)
+                 ;; and the trash directory is in a different
+                 ;; filesystem, rename-file will error out, even when
+                 ;; 'overwrite' is non-nil.  Rather than worry about
+                 ;; whether we're crossing filesystems, just check if
+                 ;; we've moving a directory and the target directory
+                 ;; already exists.  That handles both the
+                 ;; same-filesystem and cross-filesystem cases.
                 (let ((delete-by-moving-to-trash nil)
                       (new-fn (file-name-concat trash-files-dir files-base)))
-                  (rename-file fn new-fn overwrite)))))))))
+                   (if (or (not is-directory)
+                           (not (file-exists-p new-fn)))
+                       (rename-file fn new-fn overwrite)
+                     (copy-directory fn
+                                     (file-name-as-directory new-fn)
+                                     t nil t)
+                     (delete-directory fn t))))))))))
+
 
 \f
 (defsubst file-attribute-type (attributes)