Lots of work

This commit is contained in:
2025-10-17 16:47:03 -07:00
parent 9ab3a6c374
commit c309b1df38
6 changed files with 284 additions and 43 deletions

View File

@ -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)))))