Flexible Lisp Blogware. Fork for personal use. Mirrored from https://github.com/kingcons/coleslaw originally.

s3.lisp 2.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. (eval-when (:compile-toplevel)
  2. (ql:quickload '(zs3)))
  3. (defpackage :coleslaw-s3
  4. (:use :cl :coleslaw :zs3))
  5. (in-package :coleslaw-s3)
  6. (defparameter *credentials* (get-credentials :s3)
  7. "The credentials to authenticate with Amazon Web Services.
  8. Stored in a file with the access key on the first line
  9. and the secret key on the second.")
  10. (defparameter *content-type-map* '(("html" . "text/html")
  11. ("css" . "text/css")
  12. ("png" . "image/png")
  13. ("jpg" . "image/jpg"))
  14. "A mapping from file extensions to content types.")
  15. (defparameter *cache* (make-hash-table :test #'equal)
  16. "A cache of keys in a given bucket hashed by etag.")
  17. (defparameter *bucket* nil
  18. "A string designating the bucket to upload to.")
  19. (defun content-type (extension)
  20. (cdr (assoc extension *content-type-map* :test #'equal)))
  21. (defun init ()
  22. (unless *credentials*
  23. (set-credentials :s3 (file-credentials "~/.aws"))
  24. (setf *credentials* (get-credentials :s3))))
  25. (defun stale-keys (&key cache)
  26. (loop for key being the hash-values in cache collecting key))
  27. (defun s3-sync (filepath &key bucket dir public-p cache)
  28. (flet ((compute-key (namestring)
  29. (subseq namestring (length (namestring (truename dir))))))
  30. (let* ((etag (file-etag filepath))
  31. (namestring (namestring filepath))
  32. (key (compute-key namestring)))
  33. (if (gethash etag cache)
  34. (remhash etag cache)
  35. (put-file filepath bucket key :public public-p
  36. :content-type (content-type (pathname-type filepath)))))))
  37. (defun dir->s3 (dir &key bucket cache public-p)
  38. (cl-fad:walk-directory dir (lambda (file)
  39. (s3-sync file :cache cache :dir dir
  40. :bucket bucket :public-p public-p))))
  41. (defmethod coleslaw::render-site :after ()
  42. (init)
  43. (let* ((keys (all-keys *bucket*)))
  44. (loop for key across keys do (setf (gethash (etag key) *cache*) key))
  45. (dir->s3 coleslaw::*output-dir* :bucket *bucket* :cache *cache* :public-p t)
  46. (when (stale-keys :cache *cache*)
  47. (delete-objects (stale-keys) *bucket*))))