Lots of work
This commit is contained in:
		
							
								
								
									
										76
									
								
								trash.lisp
									
									
									
									
									
								
							
							
						
						
									
										76
									
								
								trash.lisp
									
									
									
									
									
								
							| @ -1,10 +1,9 @@ | ||||
| (in-package :cl-xdg-trash) | ||||
|  | ||||
| (declaim (ftype (function () (or integer null)) getuid)) | ||||
| (declaim (ftype (function () integer) getuid)) | ||||
| (defun getuid () | ||||
|   "Return the current user's UID, or nil if it cannot be determined." | ||||
|   #+sbcl (sb-posix:getuid) | ||||
|   #-(or sbcl) nil) | ||||
|   "Return the current user's UID." | ||||
|   (osicat-posix:getuid)) | ||||
|  | ||||
| (declaim (ftype (function (&key (:homedir (or pathname string null))) pathname) | ||||
|                 xdg-data-home)) | ||||
| @ -77,16 +76,73 @@ directory)." | ||||
|              (car (find-trash-dirs-for-toplevel root))) | ||||
|         (user-home-trash-directory)))) | ||||
|  | ||||
| (declaim (ftype (function ((or pathname string)) t) trash-file)) | ||||
| (defun trash-file (path) | ||||
| (declaim (ftype (function ((or pathname string) &optional t) t) trash-file)) | ||||
| (defun trash-file (path &optional (update-size-cache t)) | ||||
|   "Move PATH to the trash. Specifically, move it to the proper trash as | ||||
| specified by the XDG standard." | ||||
| specified by the XDG standard. If UPDATE-SIZE-CACHE is non-nil (the default) | ||||
| also update the directory size cache." | ||||
|   (let* ((path (merge-pathnames (ensure-nonwild-pathname path) (uiop:getcwd))) | ||||
|          (trash-directory (trash-directory-for-file path)) | ||||
|          (trashinfo (make-trashinfo-for trash-directory path)) | ||||
|          (files-dir (ensure-directories-exist (merge-pathnames | ||||
|                                                #P"files/" trash-directory) | ||||
|                                               :verbose nil))) | ||||
|     (rename-file path (merge-pathnames | ||||
|                        (make-pathname :name (trashinfo-name trashinfo)) | ||||
|                        files-dir)))) | ||||
|     (osicat-posix:rename (uiop:native-namestring path) | ||||
|                          (uiop:native-namestring | ||||
|                           (merge-pathnames | ||||
|                            (make-pathname :name (trashinfo-name trashinfo)) | ||||
|                            files-dir))) | ||||
|     (when update-size-cache | ||||
|       (trashed-file-size trash-directory (trashinfo-name trashinfo))))) | ||||
|  | ||||
| (declaim (ftype (function ((or pathname string list)) list) | ||||
|                 normalize-trash-directories) | ||||
|          (inline normalize-trash-directories)) | ||||
| (defun normalize-trash-directories (trash-directories) | ||||
|   "Normalize TRASH-DIRECTORIES to a non-wild list of pathnames." | ||||
|   (if (or (stringp trash-directories) (pathnamep trash-directories)) | ||||
|       (list (ensure-nonwild-pathname trash-directories :ensure-directory t)) | ||||
|       (mapcar #'(lambda (elt) | ||||
|                   (ensure-nonwild-pathname elt :ensure-directory t)) | ||||
|               trash-directories))) | ||||
|  | ||||
| (declaim (ftype (function (pathname) list) list-trashed-files-for-directory)) | ||||
| (defun list-trasheds-file-for-directory (trash-directory) | ||||
|   "Return a list of trashinfo objects for every trashed file in | ||||
| TRASH-DIRECTORY." | ||||
|   (let ((info-dir (merge-pathnames #P"info/" trash-directory))) | ||||
|     (mapcan #'(lambda (path) | ||||
|                 (let ((name (file-or-dir-namestring path))) | ||||
|                   (when (uiop:string-suffix-p name ".trashinfo") | ||||
|                     (list (parse-trashinfo-file | ||||
|                            trash-directory | ||||
|                            (subseq name 0 (- (length name) | ||||
|                                              (length ".trashinfo")))))))) | ||||
|             (uiop:directory-files info-dir)))) | ||||
|  | ||||
| (declaim (ftype (function (&optional (or pathname string list)) list) | ||||
|                 normalize-trash-directories)) | ||||
| (defun list-trashed-files (&optional (trash-directories (list-trash-directories))) | ||||
|   "Return a list of trashinfo objects for each trashed file in | ||||
| TRASH-DIRECTORIES. TRASH-DIRECTORIES can also be a single path." | ||||
|   (mapcan #'list-trashed-file-for-directory | ||||
|           (normalize-trash-directories trash-directories))) | ||||
|  | ||||
| (declaim (ftype (function (trashinfo &optional t) t) restore-file)) | ||||
| (defun restore-file (trashinfo &optional (update-size-cache t)) | ||||
|   "Restore the file pointed to by TRASHINFO. If UPDATE-SIZE-CACHE is non-nil | ||||
| (the default), also update the directory size cache." | ||||
|   (osicat-posix:rename | ||||
|    (uiop:native-namestring (trashinfo-trashed-file trashinfo)) | ||||
|    (uiop:native-namestring (trashinfo-original-path trashinfo))) | ||||
|   (handler-bind | ||||
|       ;; attempt to re-trash the file in case of error | ||||
|       ((t #'(lambda (e) | ||||
|               (osicat-posix:rename | ||||
|                (uiop:native-namestring (trashinfo-original-path trashinfo)) | ||||
|                (uiop:native-namestring (trashinfo-trashed-file trashinfo))) | ||||
|               (signal e)))) | ||||
|     (delete-file (trashinfo-info-file trashinfo)) | ||||
|     (when update-size-cache | ||||
|       (trashed-file-size (trashinfo-trash-directory trashinfo) | ||||
|                          (trashinfo-name trashinfo))))) | ||||
|  | ||||
		Reference in New Issue
	
	Block a user