diff options
| author | Chong Yidong | 2009-06-28 04:54:06 +0000 |
|---|---|---|
| committer | Chong Yidong | 2009-06-28 04:54:06 +0000 |
| commit | d63a01efdb2c9cf411b4bc806f8fea397d68d398 (patch) | |
| tree | 7e1f4dc7d4fb0269eaa1091a0686a894af249187 | |
| parent | 09964e7ddd73e7224538a34fa1ccf375e206f19c (diff) | |
| download | emacs-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/NEWS | 6 | ||||
| -rw-r--r-- | lisp/ChangeLog | 12 | ||||
| -rw-r--r-- | lisp/files.el | 171 |
3 files changed, 156 insertions, 33 deletions
| @@ -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 | ||
| 28 | means that `move-file-to-trash' trashes files according to | ||
| 29 | freedesktop.org specifications, the same method used by the Gnome, | ||
| 30 | KDE, and XFCE desktops. (This change has no effect on Windows, which | ||
| 31 | uses `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 @@ | |||
| 1 | 2009-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 | |||
| 8 | 2009-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 | |||
| 1 | 2009-06-28 Glenn Morris <rgm@gnu.org> | 13 | 2009-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. |
| 6015 | This directory is only used when the function `system-move-file-to-trash' is | 6015 | This directory is only used when the function `system-move-file-to-trash' |
| 6016 | not defined. Relative paths are interpreted relative to `default-directory'. | 6016 | is not defined. |
| 6017 | See also `delete-by-moving-to-trash'." | 6017 | Relative paths are interpreted relative to `default-directory'. |
| 6018 | If 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. |
| 6026 | This function is called by `delete-file' and `delete-directory' when | 6029 | When `delete-by-moving-to-trash' is non-nil, this function is |
| 6027 | `delete-by-moving-to-trash' is non-nil. On platforms that define | 6030 | called by `delete-file' and `delete-directory' instead of |
| 6028 | `system-move-file-to-trash', that function is used to move FILENAME to the | 6031 | deleting files outright. |
| 6029 | system trash, otherwise FILENAME is moved to `trash-directory'. | 6032 | |
| 6030 | Returns nil on success." | 6033 | If the function `system-move-file-to-trash' is defined, call it |
| 6034 | with FILENAME as an argument. | ||
| 6035 | Otherwise, if `trash-directory' is non-nil, move FILENAME to that | ||
| 6036 | directory. | ||
| 6037 | Otherwise, 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) |