(in-package :cl-xdg-trash/trashinfo) (define-condition trashinfo-format-error (error) ((message :accessor trashinfo-format-error-message :initarg :message :type string :documentation "A message describing the error.") (line-number :accessor trashinfo-format-error-line-number :initarg :line-number :type (integer 1) :documentation "The line number of the error. The first line is line 1.") (context :accessor trashinfo-format-error-context :initarg :context :type string :documentation "The text of the line causing the error.") (source-file :accessor trashinfo-format-error-source-file :initarg :source-file :type pathname :documentation "The path to the file the error happened in.")) (:report (lambda (condition stream) (with-slots (message line-number source-file) condition (format stream "Error parsing ~A on line ~A: ~A." source-file line-number message))))) (defclass trashinfo () ((trash-directory :reader trashinfo-trash-directory :initarg :trash-directory :type pathname :documentation "The path to the trash directory that this trashinfo file belongs to.") (name :accessor trashinfo-name :initarg :name :type string :documentation "The name of this trashinfo file without the extension.") (path :accessor trashinfo-path :initarg :path :type pathname :documentation "Path to the original location of the file.") (deletion-date :accessor trashinfo-deletion-date :initarg :deletion-date :type local-time:timestamp :documentation "The time the corresponding file was trashed.")) (:documentation "Represents a .trashinfo file.")) (declaim (ftype (function ((or pathname string) string) trashinfo))) (defun parse-trashinfo-from-string (trash-directory name) "Parse the trashinfo file NAME (which should not have an extension) in TRASH-DIRECTORY." (let ((source-file (merge-pathnames (make-pathname :name name :directory '(:relative "info")) trash-directory))) (with-open-file (in source-file :if-does-not-exist :error) (let ((first-line (read-line in :eof-error-p nil))) (unless first-line (error 'trashinfo-format-error :line-number 1 :source-file source-file :context "" :message "Unexpected end-of-file")) (unless (equal first-line "[Trash Info]") (error 'trashinfo-format-error :line-number 1 :source-file source-file :context first-line :message "First line should be \"[Trash Info]\""))) (loop for line = (read-line in :eof-error-p nil) while line) ))) (defmethod trashinfo-trashed-file ()) ;; Local Variables: ;; jinx-local-words: "trashinfo" ;; End: