]> git.eshelyaron.com Git - emacs.git/commitdiff
Add remote-file-name-inhibit-delete-by-moving-to-trash
authorMichael Albinus <michael.albinus@gmx.de>
Sun, 8 Jan 2023 18:24:17 +0000 (19:24 +0100)
committerMichael Albinus <michael.albinus@gmx.de>
Sun, 8 Jan 2023 18:24:17 +0000 (19:24 +0100)
* doc/emacs/files.texi (Misc File Ops):
* doc/lispref/files.texi (Changing Files):
* doc/misc/tramp.texi (Frequently Asked Questions):
* etc/NEWS: Explain remote-file-name-inhibit-delete-by-moving-to-trash.

* lisp/files.el (remote-file-name-inhibit-delete-by-moving-to-trash):
New defcustom.  (Bug#60460)

* lisp/net/ange-ftp.el (ange-ftp-delete-file):
* lisp/net/tramp.el (tramp-skeleton-delete-directory):
Handle `remote-file-name-inhibit-delete-by-moving-to-trash'.
(tramp-skeleton-delete-file): New defmacro.

* lisp/net/tramp-adb.el (tramp-adb-handle-delete-file):
* lisp/net/tramp-fuse.el (tramp-fuse-handle-delete-file):
* lisp/net/tramp-gvfs.el (tramp-gvfs-handle-delete-file):
* lisp/net/tramp-sh.el (tramp-sh-handle-delete-file):
* lisp/net/tramp-smb.el (tramp-smb-handle-delete-file):
* lisp/net/tramp-sudoedit.el (tramp-sudoedit-handle-delete-file): Use it.

* lisp/net/tramp-crypt.el (tramp-crypt-handle-delete-directory)
(tramp-crypt-handle-delete-file): Rearrange.

* lisp/net/tramp-fuse.el (tramp-fuse-handle-delete-directory):
Use `tramp-skeleton-delete-directory'.

* test/lisp/net/tramp-tests.el
(remote-file-name-inhibit-delete-by-moving-to-trash): Declare.
(tramp-test07-file-exists-p, tramp-test14-delete-directory)
(tramp-test48-unload): Extend tests.

15 files changed:
doc/emacs/files.texi
doc/lispref/files.texi
doc/misc/tramp.texi
etc/NEWS
lisp/files.el
lisp/net/ange-ftp.el
lisp/net/tramp-adb.el
lisp/net/tramp-crypt.el
lisp/net/tramp-fuse.el
lisp/net/tramp-gvfs.el
lisp/net/tramp-sh.el
lisp/net/tramp-smb.el
lisp/net/tramp-sudoedit.el
lisp/net/tramp.el
test/lisp/net/tramp-tests.el

index 6a9103d3a09979cc1e202fb5ddc970c31da7a863..42e252c417b25d3563bf60a8a0277562e8741c1d 100644 (file)
@@ -1888,6 +1888,11 @@ following in the Trash directory:
 liable to also delete this @code{.dir-locals.el} file, so this should
 only be done if you delete files from the Trash directory manually.
 
+@vindex remote-file-name-inhibit-delete-by-moving-to-trash
+  If the variable @code{remote-file-name-inhibit-delete-by-moving-to-trash}
+is non-@code{nil}, remote files are never moved to the Trash.  They
+are deleted instead.
+
 @ifnottex
   If a file is under version control (@pxref{Version Control}), you
 should delete it using @kbd{M-x vc-delete-file} instead of @kbd{M-x
index 91643530f7f0cca23a9beb75069c1af240a964d9..5cc4c1e7ddfa9d89da58cd55ca52fafec0a4f071 100644 (file)
@@ -1871,6 +1871,11 @@ no prefix argument is given, and @code{nil} otherwise.
 See also @code{delete-directory} in @ref{Create/Delete Dirs}.
 @end deffn
 
+@defopt remote-file-name-inhibit-delete-by-moving-to-trash
+If this variable is non-@code{nil}, remote files are never moved to
+the Trash.  They are deleted instead.
+@end defopt
+
 @cindex file permissions, setting
 @cindex permissions, file
 @cindex file modes, setting
index 7f66dc9e849f26feb16a48e119a2c765405eb356..a8a59f982fcfdfc49b2931e78968846c581f931d 100644 (file)
@@ -5215,9 +5215,10 @@ them, @ref{Misc File Ops, Trashing , , emacs}.
 @ifnotinfo
 them.
 @end ifnotinfo
-Remote files are always trashed to the local trash, except remote
-encrypted files (@pxref{Keeping files encrypted}), which are deleted
-anyway.
+Remote files are always trashed to the local trash, except the user
+option @code{remote-file-name-inhibit-delete-by-moving-to-trash} is
+non-@code{nil}, or it is a remote encrypted file (@pxref{Keeping files
+encrypted}), which are deleted anyway.
 
 If Emacs is configured to use the XDG conventions for the trash
 directory, remote files cannot be restored with the respective tools,
index 690e9c3faa9016e219170094d6f1cab2bcf3ed99..60dab575da65ccbdbb0d92789fe828ea32dc491e 100644 (file)
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -45,6 +45,11 @@ example, as part of preview for iconified frames.
 ** 'write-region-inhibit-fsync' now defaults to t in interactive mode,
 as it has in batch mode since Emacs 24.
 
++++
+** New user option 'remote-file-name-inhibit-delete-by-moving-to-trash'.
+When non-nil, this option suppresses moving remote files to the local
+trash when deleting.  Default is nil.
+
 \f
 * Editing Changes in Emacs 30.1
 
index e1b7a990b150d6b0d554916f9cad1dc4b8213494..d0167bf38148e922bd1a72e80eeb6a7dd184656e 100644 (file)
@@ -6336,6 +6336,12 @@ RECURSIVE if DIRECTORY is nonempty."
                  directory-exists))
        (files--force recursive #'delete-directory-internal directory))))))
 
+(defcustom remote-file-name-inhibit-delete-by-moving-to-trash nil
+  "Whether remote files shall be moved to the Trash.
+This overrules any setting of `delete-by-moving-to-trash'."
+  :version "30.1"
+  :type 'boolean)
+
 (defun file-equal-p (file1 file2)
   "Return non-nil if files FILE1 and FILE2 name the same file.
 If FILE1 or FILE2 does not exist, the return value is unspecified."
index 41c28672aae736e8d9e47226f2aa33ee7d161d57..a14122f815ad7ba5ab02036176edfe0933394e31 100644 (file)
@@ -3534,7 +3534,8 @@ system TYPE.")
   (setq file (expand-file-name file))
   (let ((parsed (ange-ftp-ftp-name file)))
     (if parsed
-        (if (and delete-by-moving-to-trash trash)
+        (if (and delete-by-moving-to-trash trash
+                (not remote-file-name-inhibit-delete-by-moving-to-trash))
            (move-file-to-trash file)
          (let* ((host (nth 0 parsed))
                 (user (nth 1 parsed))
index 619d29bb4d6e5ad7a6f8fbe3d422d78bb79fc77b..493a9fb39a9762d18bdae673814c8c036250e753 100644 (file)
@@ -424,14 +424,10 @@ Emacs dired can't find files."
 
 (defun tramp-adb-handle-delete-file (filename &optional trash)
   "Like `delete-file' for Tramp files."
-  (setq filename (expand-file-name filename))
-  (with-parsed-tramp-file-name filename nil
-    (tramp-flush-file-properties v localname)
-    (if (and delete-by-moving-to-trash trash)
-       (move-file-to-trash filename)
-      (tramp-adb-barf-unless-okay
-       v (format "rm %s" (tramp-shell-quote-argument localname))
-       "Couldn't delete %s" filename))))
+  (tramp-skeleton-delete-file filename trash
+    (tramp-adb-barf-unless-okay
+     v (format "rm %s" (tramp-shell-quote-argument localname))
+     "Couldn't delete %s" filename)))
 
 (defun tramp-adb-handle-file-name-all-completions (filename directory)
   "Like `file-name-all-completions' for Tramp files."
index 61d1c529619502f350fff4e521933bf5941451ee..507fd43241905b5d934f6dea4e6384a6324588fb 100644 (file)
@@ -689,17 +689,17 @@ absolute file names."
     (directory &optional recursive _trash)
   "Like `delete-directory' for Tramp files."
   (with-parsed-tramp-file-name (expand-file-name directory) nil
-    (tramp-flush-directory-properties v localname)
     (let (tramp-crypt-enabled)
-      (delete-directory (tramp-crypt-encrypt-file-name directory) recursive))))
+      (delete-directory (tramp-crypt-encrypt-file-name directory) recursive))
+    (tramp-flush-directory-properties v localname)))
 
 ;; Encrypted files won't be trashed.
 (defun tramp-crypt-handle-delete-file (filename &optional _trash)
   "Like `delete-file' for Tramp files."
   (with-parsed-tramp-file-name (expand-file-name filename) nil
-    (tramp-flush-file-properties v localname)
     (let (tramp-crypt-enabled)
-      (delete-file (tramp-crypt-encrypt-file-name filename)))))
+      (delete-file (tramp-crypt-encrypt-file-name filename)))
+    (tramp-flush-file-properties v localname)))
 
 (defun tramp-crypt-handle-directory-files
     (directory &optional full match nosort count)
index c8754e2b03d968d5858fd48d7de35227a92c76fe..b846caadc18a9a1c3da4c7cc52ce288a1369176b 100644 (file)
 (defun tramp-fuse-handle-delete-directory
     (directory &optional recursive trash)
   "Like `delete-directory' for Tramp files."
-  (with-parsed-tramp-file-name (expand-file-name directory) nil
-    (tramp-flush-directory-properties v localname)
+  (tramp-skeleton-delete-directory directory recursive trash
     (delete-directory (tramp-fuse-local-file-name directory) recursive trash)))
 
 (defun tramp-fuse-handle-delete-file (filename &optional trash)
   "Like `delete-file' for Tramp files."
-  (with-parsed-tramp-file-name (expand-file-name filename) nil
-    (delete-file (tramp-fuse-local-file-name filename) trash)
-    (tramp-flush-file-properties v localname)))
+  (tramp-skeleton-delete-file filename trash
+    (delete-file (tramp-fuse-local-file-name filename) trash)))
 
 (defvar tramp-fuse-remove-hidden-files nil
   "Remove hidden files from directory listings.")
index bb81b3eb66c31c5af54686ff9128ddf54224c6c2..cca7a5fe2474666d104664d761f25d3d782c6f20 100644 (file)
@@ -1139,18 +1139,15 @@ file names."
 
 (defun tramp-gvfs-handle-delete-file (filename &optional trash)
   "Like `delete-file' for Tramp files."
-  (with-parsed-tramp-file-name (expand-file-name filename) nil
-    (tramp-flush-file-properties v localname)
-    (if (and delete-by-moving-to-trash trash)
-       (move-file-to-trash filename)
-      (unless (and (tramp-gvfs-send-command
-                   v "gvfs-rm" (tramp-gvfs-url-file-name filename))
-                  (not (tramp-gvfs-info filename)))
-       ;; Propagate the error.
-       (with-current-buffer (tramp-get-connection-buffer v)
-         (goto-char (point-min))
-         (tramp-error-with-buffer
-          nil v 'file-error "Couldn't delete %s" filename))))))
+  (tramp-skeleton-delete-file filename trash
+    (unless (and (tramp-gvfs-send-command
+                 v "gvfs-rm" (tramp-gvfs-url-file-name filename))
+                (not (tramp-gvfs-info filename)))
+      ;; Propagate the error.
+      (with-current-buffer (tramp-get-connection-buffer v)
+       (goto-char (point-min))
+       (tramp-error-with-buffer
+        nil v 'file-error "Couldn't delete %s" filename)))))
 
 (defun tramp-gvfs-handle-expand-file-name (name &optional dir)
   "Like `expand-file-name' for Tramp files."
index fbdd40dd1d2ba151568170047cffbe2ff8d1bc15..4647600071ce0d56f24715974ca8354ffa4b8664 100644 (file)
@@ -2567,14 +2567,10 @@ The method used must be an out-of-band method."
 
 (defun tramp-sh-handle-delete-file (filename &optional trash)
   "Like `delete-file' for Tramp files."
-  (setq filename (expand-file-name (expand-file-name filename)))
-  (with-parsed-tramp-file-name filename nil
-    (if (and delete-by-moving-to-trash trash)
-       (move-file-to-trash filename)
-      (tramp-barf-unless-okay
-       v (format "rm -f %s" (tramp-shell-quote-argument localname))
-       "Couldn't delete %s" filename))
-    (tramp-flush-file-properties v localname)))
+  (tramp-skeleton-delete-file filename trash
+    (tramp-barf-unless-okay
+     v (format "rm -f %s" (tramp-shell-quote-argument localname))
+       "Couldn't delete %s" filename)))
 
 ;; Dired.
 
index f31865d498d6194b1d52dcaf53d5273b08da25e8..d6f3cca97336fd8135b0c3b445808ec7dad36e44 100644 (file)
@@ -695,24 +695,17 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored."
 
 (defun tramp-smb-handle-delete-file (filename &optional trash)
   "Like `delete-file' for Tramp files."
-  (setq filename (expand-file-name filename))
-  (when (file-exists-p filename)
-    (with-parsed-tramp-file-name filename nil
-      ;; We must also flush the cache of the directory, because
-      ;; `file-attributes' reads the values from there.
-      (tramp-flush-file-properties v localname)
-      (if (and delete-by-moving-to-trash trash)
-         (move-file-to-trash filename)
-       (unless (tramp-smb-send-command
-                v (format
-                   "%s %s"
-                   (if (tramp-smb-get-cifs-capabilities v) "posix_unlink" "rm")
-                   (tramp-smb-shell-quote-localname v)))
-         ;; Error.
-         (with-current-buffer (tramp-get-connection-buffer v)
-           (goto-char (point-min))
-           (search-forward-regexp tramp-smb-errors nil t)
-           (tramp-error v 'file-error "%s `%s'" (match-string 0) filename)))))))
+  (tramp-skeleton-delete-file filename trash
+    (unless (tramp-smb-send-command
+            v (format
+               "%s %s"
+               (if (tramp-smb-get-cifs-capabilities v) "posix_unlink" "rm")
+               (tramp-smb-shell-quote-localname v)))
+      ;; Error.
+      (with-current-buffer (tramp-get-connection-buffer v)
+       (goto-char (point-min))
+       (search-forward-regexp tramp-smb-errors nil t)
+       (tramp-error v 'file-error "%s `%s'" (match-string 0) filename)))))
 
 (defun tramp-smb-handle-expand-file-name (name &optional dir)
   "Like `expand-file-name' for Tramp files."
index c4e1d32f525f3b71ad619af943fd4bf77b071406..2660dbb1facb99170e04c2f3ecbf2d2813d7ed81 100644 (file)
@@ -347,17 +347,14 @@ absolute file names."
 
 (defun tramp-sudoedit-handle-delete-file (filename &optional trash)
   "Like `delete-file' for Tramp files."
-  (with-parsed-tramp-file-name (expand-file-name filename) nil
-    (tramp-flush-file-properties v localname)
-    (if (and delete-by-moving-to-trash trash)
-       (move-file-to-trash filename)
-      (unless (tramp-sudoedit-send-command
-              v "rm" "-f" (file-name-unquote localname))
-       ;; Propagate the error.
-       (with-current-buffer (tramp-get-connection-buffer v)
-         (goto-char (point-min))
-         (tramp-error-with-buffer
-          nil v 'file-error "Couldn't delete %s" filename))))))
+  (tramp-skeleton-delete-file filename trash
+    (unless (tramp-sudoedit-send-command
+            v "rm" "-f" (file-name-unquote localname))
+      ;; Propagate the error.
+      (with-current-buffer (tramp-get-connection-buffer v)
+       (goto-char (point-min))
+       (tramp-error-with-buffer
+        nil v 'file-error "Couldn't delete %s" filename)))))
 
 (defun tramp-sudoedit-handle-expand-file-name (name &optional dir)
   "Like `expand-file-name' for Tramp files.
index 4bf0fdefc0ba3b0b5175fadabdccb39fd625c411..b8475b7cb4861d79d94c1912a116612e1ec3a31b 100644 (file)
@@ -3399,15 +3399,35 @@ BODY is the backend specific code."
 BODY is the backend specific code."
   (declare (indent 3) (debug t))
   `(with-parsed-tramp-file-name (expand-file-name ,directory) nil
-    (if (and delete-by-moving-to-trash ,trash)
-       ;; Move non-empty dir to trash only if recursive deletion was
-       ;; requested.
-       (if (not (or ,recursive (tramp-compat-directory-empty-p ,directory)))
-           (tramp-error
-            v 'file-error "Directory is not empty, not moving to trash")
-         (move-file-to-trash ,directory))
-      ,@body)
-    (tramp-flush-directory-properties v localname)))
+     (let ((delete-by-moving-to-trash
+           (and delete-by-moving-to-trash
+                ;; This variable exists since Emacs 30.1.
+                (not (bound-and-true-p
+                      remote-file-name-inhibit-delete-by-moving-to-trash)))))
+       (if (and delete-by-moving-to-trash ,trash)
+          ;; Move non-empty dir to trash only if recursive deletion was
+          ;; requested.
+          (if (not (or ,recursive (tramp-compat-directory-empty-p ,directory)))
+              (tramp-error
+               v 'file-error "Directory is not empty, not moving to trash")
+            (move-file-to-trash ,directory))
+        ,@body)
+       (tramp-flush-directory-properties v localname))))
+
+(defmacro tramp-skeleton-delete-file (filename &optional trash &rest body)
+  "Skeleton for `tramp-*-handle-delete-file'.
+BODY is the backend specific code."
+  (declare (indent 2) (debug t))
+  `(with-parsed-tramp-file-name (expand-file-name ,filename) nil
+     (let ((delete-by-moving-to-trash
+           (and delete-by-moving-to-trash
+                ;; This variable exists since Emacs 30.1.
+                (not (bound-and-true-p
+                      remote-file-name-inhibit-delete-by-moving-to-trash)))))
+       (if (and delete-by-moving-to-trash ,trash)
+          (move-file-to-trash ,filename)
+        ,@body)
+       (tramp-flush-file-properties v localname))))
 
 (defmacro tramp-skeleton-directory-files
     (directory &optional full match nosort count &rest body)
index 90f6fcd6b150e5d9a34b5e367305321e7ca970f3..dd3de27d3b9f08f9a646fef3021256120d1e4844 100644 (file)
@@ -80,6 +80,9 @@
 (defvar remote-file-name-inhibit-locks)
 (defvar dired-copy-dereference)
 
+;; Declared in Emacs 30.
+(defvar remote-file-name-inhibit-delete-by-moving-to-trash)
+
 ;; `ert-resource-file' was introduced in Emacs 28.1.
 (unless (macrop 'ert-resource-file)
   (eval-and-compile
@@ -2345,7 +2348,24 @@ This checks also `file-name-as-directory', `file-name-directory',
                (expand-file-name
                 (file-name-nondirectory tmp-name) trash-directory))))
          (delete-directory trash-directory 'recursive)
-         (should-not (file-exists-p trash-directory)))))))
+         (should-not (file-exists-p trash-directory))))
+
+      ;; Setting `remote-file-name-inhibit-delete-by-moving-to-trash'
+      ;; prevents trashing remote files.
+      (let ((trash-directory (tramp--test-make-temp-name 'local quoted))
+           (delete-by-moving-to-trash t)
+           (remote-file-name-inhibit-delete-by-moving-to-trash t))
+       (make-directory trash-directory)
+       (should-not (file-exists-p tmp-name))
+       (write-region "foo" nil tmp-name)
+       (should (file-exists-p tmp-name))
+       (delete-file tmp-name 'trash)
+       (should-not (file-exists-p tmp-name))
+       (should-not
+        (file-exists-p
+         (expand-file-name (file-name-nondirectory tmp-name) trash-directory)))
+       (delete-directory trash-directory 'recursive)
+       (should-not (file-exists-p trash-directory))))))
 
 (ert-deftest tramp-test08-file-local-copy ()
   "Check `file-local-copy'."
@@ -2953,7 +2973,23 @@ This tests also `file-directory-p' and `file-accessible-directory-p'."
             "%s/%s/%s/bla" trash-directory (file-name-nondirectory tmp-name1)
             (file-name-nondirectory tmp-name2))))
          (delete-directory trash-directory 'recursive)
-         (should-not (file-exists-p trash-directory)))))))
+         (should-not (file-exists-p trash-directory))))
+
+      ;; Setting `remote-file-name-inhibit-delete-by-moving-to-trash'
+      ;; prevents trashing remote files.
+      (let ((trash-directory (tramp--test-make-temp-name 'local quoted))
+           (delete-by-moving-to-trash t)
+           (remote-file-name-inhibit-delete-by-moving-to-trash t))
+       (make-directory trash-directory)
+       (make-directory tmp-name1)
+       (should (file-directory-p tmp-name1))
+       (delete-directory tmp-name1 nil 'trash)
+       (should-not (file-exists-p tmp-name1))
+       (should-not
+        (file-exists-p
+         (expand-file-name (file-name-nondirectory tmp-name1) trash-directory)))
+       (delete-directory trash-directory 'recursive)
+       (should-not (file-exists-p trash-directory))))))
 
 (ert-deftest tramp-test15-copy-directory ()
   "Check `copy-directory'."
@@ -7518,6 +7554,8 @@ Since it unloads Tramp, it shall be the last test to run."
          ;; `tramp-register-archive-file-name-handler' is autoloaded
          ;; in Emacs < 29.1.
          (not (eq 'tramp-register-archive-file-name-handler x))
+         ;; `tramp-compat-rx' is autoloaded in Emacs 29.1.
+         (not (eq 'tramp-compat-rx x))
          (not (string-match-p
                (rx bol "tramp" (? "-archive") (** 1 2 "-") "test")
                (symbol-name x)))
@@ -7577,6 +7615,8 @@ If INTERACTIVE is non-nil, the tests are run interactively."
 ;; * file-equal-p (partly done in `tramp-test21-file-links')
 ;; * file-in-directory-p
 ;; * file-name-case-insensitive-p
+;; * memory-info
+;; * tramp-get-home-directory
 ;; * tramp-get-remote-gid
 ;; * tramp-get-remote-groups
 ;; * tramp-get-remote-uid