aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChong Yidong2009-06-28 04:54:06 +0000
committerChong Yidong2009-06-28 04:54:06 +0000
commitd63a01efdb2c9cf411b4bc806f8fea397d68d398 (patch)
tree7e1f4dc7d4fb0269eaa1091a0686a894af249187
parent09964e7ddd73e7224538a34fa1ccf375e206f19c (diff)
downloademacs-d63a01efdb2c9cf411b4bc806f8fea397d68d398.tar.gz
emacs-d63a01efdb2c9cf411b4bc806f8fea397d68d398.zip
* files.el (trash-directory): Change default to nil.
(move-file-to-trash): If trash-directory is nil and system-move-file-to-trash is unbound, perform freedesktop-style trashing. * NEWS: Document change.
-rw-r--r--etc/NEWS6
-rw-r--r--lisp/ChangeLog12
-rw-r--r--lisp/files.el171
3 files changed, 156 insertions, 33 deletions
diff --git a/etc/NEWS b/etc/NEWS
index d4819fc040e..69752517098 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -24,6 +24,12 @@ so we will look at it and add it to the manual.
24 24
25* Changes in Emacs 23.2 25* Changes in Emacs 23.2
26 26
27** The default value of `trash-directory' has changed to nil, which
28means that `move-file-to-trash' trashes files according to
29freedesktop.org specifications, the same method used by the Gnome,
30KDE, and XFCE desktops. (This change has no effect on Windows, which
31uses `system-move-file-to-trash' for trashing.)
32
27 33
28* Changes in Specialized Modes and Packages in Emacs 23.2 34* Changes in Specialized Modes and Packages in Emacs 23.2
29 35
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index a6aa7a6318e..cd50bba543a 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,15 @@
12009-06-28 Chong Yidong <cyd@stupidchicken.com>
2
3 * files.el (trash-directory): Change default to nil.
4 (move-file-to-trash): If trash-directory is nil and
5 system-move-file-to-trash is unbound, perform freedesktop-style
6 trashing.
7
82009-06-28 David De La Harpe Golden <david@harpegolden.net>
9
10 * files.el (move-file-to-trash): Add freedesktop trash
11 support (Bug#973).
12
12009-06-28 Glenn Morris <rgm@gnu.org> 132009-06-28 Glenn Morris <rgm@gnu.org>
2 14
3 * autorevert.el (global-auto-revert-non-file-buffers) 15 * autorevert.el (global-auto-revert-non-file-buffers)
diff --git a/lisp/files.el b/lisp/files.el
index 8718a9668c9..344b31db961 100644
--- a/lisp/files.el
+++ b/lisp/files.el
@@ -6010,47 +6010,152 @@ based on existing mode bits, as in \"og+rX-w\"."
6010 6010
6011 6011
6012;; Trashcan handling. 6012;; Trashcan handling.
6013(defcustom trash-directory (convert-standard-filename "~/.Trash") 6013(defcustom trash-directory nil
6014 "Directory for `move-file-to-trash' to move files and directories to. 6014 "Directory for `move-file-to-trash' to move files and directories to.
6015This directory is only used when the function `system-move-file-to-trash' is 6015This directory is only used when the function `system-move-file-to-trash'
6016not defined. Relative paths are interpreted relative to `default-directory'. 6016is not defined.
6017See also `delete-by-moving-to-trash'." 6017Relative paths are interpreted relative to `default-directory'.
6018If the value is nil, Emacs uses a freedesktop.org-style trashcan."
6018 :type 'directory 6019 :type 'directory
6019 :group 'auto-save 6020 :group 'auto-save
6020 :version "23.1") 6021 :version "23.2")
6022
6023(defvar trash--hexify-table)
6021 6024
6022(declare-function system-move-file-to-trash "w32fns.c" (filename)) 6025(declare-function system-move-file-to-trash "w32fns.c" (filename))
6023 6026
6024(defun move-file-to-trash (filename) 6027(defun move-file-to-trash (filename)
6025 "Move file (or directory) name FILENAME to the trash. 6028 "Move the file (or directory) named FILENAME to the trash.
6026This function is called by `delete-file' and `delete-directory' when 6029When `delete-by-moving-to-trash' is non-nil, this function is
6027`delete-by-moving-to-trash' is non-nil. On platforms that define 6030called by `delete-file' and `delete-directory' instead of
6028`system-move-file-to-trash', that function is used to move FILENAME to the 6031deleting files outright.
6029system trash, otherwise FILENAME is moved to `trash-directory'. 6032
6030Returns nil on success." 6033If the function `system-move-file-to-trash' is defined, call it
6034 with FILENAME as an argument.
6035Otherwise, if `trash-directory' is non-nil, move FILENAME to that
6036 directory.
6037Otherwise, trash FILENAME using the freedesktop.org conventions,
6038 like the GNOME, KDE and XFCE desktop environments. Emacs only
6039 moves files to \"home trash\", ignoring per-volume trashcans."
6031 (interactive "fMove file to trash: ") 6040 (interactive "fMove file to trash: ")
6032 (cond 6041 (cond (trash-directory
6033 ((fboundp 'system-move-file-to-trash) 6042 ;; If `trash-directory' is non-nil, move the file there.
6034 (system-move-file-to-trash filename)) 6043 (let* ((trash-dir (expand-file-name trash-directory))
6035 (t 6044 (fn (directory-file-name (expand-file-name filename)))
6036 (let* ((trash-dir (expand-file-name trash-directory)) 6045 (new-fn (expand-file-name (file-name-nondirectory fn)
6037 (fn (directory-file-name (expand-file-name filename))) 6046 trash-dir)))
6038 (fn-nondir (file-name-nondirectory fn)) 6047 ;; We can't trash a parent directory of trash-directory.
6039 (new-fn (expand-file-name fn-nondir trash-dir))) 6048 (if (string-match fn trash-dir)
6040 (or (file-directory-p trash-dir) 6049 (error "Trash directory `%s' is a subdirectory of `%s'"
6041 (make-directory trash-dir t)) 6050 trash-dir filename))
6042 (and (file-exists-p new-fn) 6051 (unless (file-directory-p trash-dir)
6043 ;; make new-fn unique. 6052 (make-directory trash-dir t))
6044 ;; example: "~/.Trash/abc.txt" -> "~/.Trash/abc.txt.~1~" 6053 ;; Ensure that the trashed file-name is unique.
6045 (let ((version-control t) 6054 (if (file-exists-p new-fn)
6046 (backup-directory-alist nil)) 6055 (let ((version-control t)
6047 (setq new-fn (car (find-backup-file-name new-fn))))) 6056 (backup-directory-alist nil))
6048 ;; stop processing if fn is same or parent directory of trash-dir. 6057 (setq new-fn (car (find-backup-file-name new-fn)))))
6049 (and (string-match fn trash-dir) 6058 (let (delete-by-moving-to-trash)
6050 (error "Filename `%s' is same or parent directory of trash-directory" 6059 (rename-file fn new-fn))))
6051 filename)) 6060 ;; If `system-move-file-to-trash' is defined, use it.
6052 (let ((delete-by-moving-to-trash nil)) 6061 ((fboundp 'system-move-file-to-trash)
6053 (rename-file fn new-fn)))))) 6062 (system-move-file-to-trash filename))
6063 ;; Otherwise, use the freedesktop.org method, as specified at
6064 ;; http://freedesktop.org/wiki/Specifications/trash-spec
6065 (t
6066 (let* ((xdg-data-dir
6067 (directory-file-name
6068 (expand-file-name "Trash"
6069 (or (getenv "XDG_DATA_HOME")
6070 "~/.local/share"))))
6071 (trash-files-dir (expand-file-name "files" xdg-data-dir))
6072 (trash-info-dir (expand-file-name "info" xdg-data-dir))
6073 (fn (directory-file-name (expand-file-name filename))))
6074
6075 ;; Check if we have permissions to delete.
6076 (unless (file-writable-p (directory-file-name
6077 (file-name-directory fn)))
6078 (error "Cannot move %s to trash: Permission denied" filename))
6079 ;; The trashed file cannot be the trash dir or its parent.
6080 (if (string-match fn trash-files-dir)
6081 (error "The trash directory %s is a subdirectory of %s"
6082 trash-files-dir filename))
6083 (if (string-match fn trash-info-dir)
6084 (error "The trash directory %s is a subdirectory of %s"
6085 trash-info-dir filename))
6086
6087 ;; Ensure that the trash directory exists; otherwise, create it.
6088 (let ((saved-default-file-modes (default-file-modes)))
6089 (set-default-file-modes ?\700)
6090 (unless (file-exists-p trash-files-dir)
6091 (make-directory trash-files-dir t))
6092 (unless (file-exists-p trash-info-dir)
6093 (make-directory trash-info-dir t))
6094 (set-default-file-modes saved-default-file-modes))
6095
6096 ;; Try to move to trash with .trashinfo undo information
6097 (save-excursion
6098 (with-temp-buffer
6099 (set-buffer-file-coding-system 'utf-8-unix)
6100 (insert "[Trash Info]\nPath=")
6101 ;; Perform url-encoding on FN. For compatibility with
6102 ;; other programs (e.g. XFCE Thunar), allow literal "/"
6103 ;; for path separators.
6104 (unless (boundp 'trash--hexify-table)
6105 (setq trash--hexify-table (make-vector 256 nil))
6106 (let ((unreserved-chars
6107 (list ?/ ?a ?b ?c ?d ?e ?f ?g ?h ?i ?j ?k ?l ?m
6108 ?n ?o ?p ?q ?r ?s ?t ?u ?v ?w ?x ?y ?z ?A
6109 ?B ?C ?D ?E ?F ?G ?H ?I ?J ?K ?L ?M ?N ?O
6110 ?P ?Q ?R ?S ?T ?U ?V ?W ?X ?Y ?Z ?0 ?1 ?2
6111 ?3 ?4 ?5 ?6 ?7 ?8 ?9 ?- ?_ ?. ?! ?~ ?* ?'
6112 ?\( ?\))))
6113 (dotimes (byte 256)
6114 (aset trash--hexify-table byte
6115 (if (memq byte unreserved-chars)
6116 (char-to-string byte)
6117 (format "%%%02x" byte))))))
6118 (mapc (lambda (byte)
6119 (insert (aref trash--hexify-table byte)))
6120 (if (multibyte-string-p fn)
6121 (encode-coding-string fn 'utf-8)
6122 fn))
6123 (insert "\nDeletionDate="
6124 (format-time-string "%Y-%m-%dT%T")
6125 "\n")
6126
6127 ;; Attempt to make .trashinfo file, trying up to 5
6128 ;; times. The .trashinfo file is opened with O_EXCL,
6129 ;; as per trash-spec 0.7, even if that can be a problem
6130 ;; on old NFS versions...
6131 (let* ((tries 5)
6132 (base-fn (expand-file-name
6133 (file-name-nondirectory fn)
6134 trash-files-dir))
6135 (new-fn base-fn)
6136 success info-fn)
6137 (while (> tries 0)
6138 (setq info-fn (expand-file-name
6139 (concat (file-name-nondirectory new-fn)
6140 ".trashinfo")
6141 trash-info-dir))
6142 (unless (condition-case nil
6143 (progn
6144 (write-region nil nil info-fn nil
6145 'quiet info-fn 'excl)
6146 (setq tries 0 success t))
6147 (file-already-exists nil))
6148 (setq tries (1- tries))
6149 ;; Uniqify new-fn. (Some file managers do not
6150 ;; like Emacs-style backup file names---e.g. bug
6151 ;; 170956 in Konqueror bug tracker.)
6152 (setq new-fn (make-temp-name (concat base-fn "_")))))
6153 (unless success
6154 (error "Cannot move %s to trash: Lock failed" filename))
6155
6156 ;; Finally, try to move the file to the trashcan.
6157 (let ((delete-by-moving-to-trash nil))
6158 (rename-file fn new-fn)))))))))
6054 6159
6055 6160
6056(define-key ctl-x-map "\C-f" 'find-file) 6161(define-key ctl-x-map "\C-f" 'find-file)