directory-ref.scm 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. ;;; Disarchive
  2. ;;; Copyright © 2020, 2021 Timothy Sample <samplet@ngyro.com>
  3. ;;;
  4. ;;; This file is part of Disarchive.
  5. ;;;
  6. ;;; Disarchive is free software: you can redistribute it and/or modify
  7. ;;; it under the terms of the GNU General Public License as published by
  8. ;;; the Free Software Foundation, either version 3 of the License, or
  9. ;;; (at your option) any later version.
  10. ;;;
  11. ;;; Disarchive is distributed in the hope that it will be useful,
  12. ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. ;;; GNU General Public License for more details.
  15. ;;;
  16. ;;; You should have received a copy of the GNU General Public License
  17. ;;; along with Disarchive. If not, see <http://www.gnu.org/licenses/>.
  18. (define-module (disarchive assemblers directory-ref)
  19. #:use-module (disarchive assemblers)
  20. #:use-module (disarchive config)
  21. #:use-module (disarchive digests)
  22. #:use-module (disarchive disassemblers)
  23. #:use-module (disarchive resolvers)
  24. #:use-module (disarchive logging)
  25. #:use-module (disarchive utils)
  26. #:use-module (gcrypt hash)
  27. #:use-module (ice-9 match)
  28. #:use-module (ice-9 popen)
  29. #:use-module (srfi srfi-1)
  30. #:use-module (srfi srfi-9)
  31. #:export (<directory-ref>
  32. make-directory-ref
  33. directory-ref?
  34. directory-ref-name
  35. directory-ref-addresses
  36. directory-ref-digest
  37. serialize-directory-ref
  38. serialized-directory-ref?
  39. deserialize-directory-ref
  40. directory-ref-file?
  41. disassemble-directory-ref
  42. directory-ref-assembler
  43. directory-ref-disassembler))
  44. ;;; Commentary:
  45. ;;;
  46. ;;; This module provides the means to construct a reference to a
  47. ;;; directory and, given that reference, restore the original
  48. ;;; directory. Each reference contains a list of addresses that each
  49. ;;; represent the directory (i.e., content addressing). There are
  50. ;;; many methods of hashing a directory and we store and use as many
  51. ;;; as we are able to. See '(disarchive resolvers)' for more about
  52. ;;; the addresses supported here.
  53. ;;;
  54. ;;; Code:
  55. ;; Data
  56. (define-record-type <directory-ref>
  57. (make-directory-ref name addresses digest)
  58. directory-ref?
  59. (name directory-ref-name) ; string
  60. (addresses directory-ref-addresses) ; list
  61. (digest directory-ref-digest)) ; <digest>
  62. (define (serialize-directory-ref directory)
  63. (match-let ((($ <directory-ref> name addresses digest) directory))
  64. `(directory-ref
  65. (version 0)
  66. (name ,name)
  67. (addresses ,@(map serialize-address addresses))
  68. (digest ,(digest->sexp digest)))))
  69. (define (serialized-directory-ref? sexp)
  70. (match sexp
  71. (('directory-ref _ ...) #t)
  72. (_ #f)))
  73. (define (deserialize-directory-ref sexp)
  74. (match sexp
  75. (('directory-ref
  76. ('version 0)
  77. ('name name)
  78. ('addresses . address-sexps)
  79. ('digest digest-sexp))
  80. (let ((addresses (map deserialize-address address-sexps))
  81. (digest (sexp->digest digest-sexp)))
  82. (make-directory-ref name addresses digest)))
  83. (_ #f)))
  84. ;; Assembly
  85. (define (assemble-directory-ref directory workspace)
  86. (match-let* ((($ <directory-ref> name addresses digest) directory)
  87. (output (digest->filename digest workspace)))
  88. (message "Assembling the directory ~a" name)
  89. (or (let* ((cache (%disarchive-directory-cache))
  90. (local (and cache (digest->filename digest cache))))
  91. (and local (directory-exists? local)
  92. (message "Found directory in cache: ~a" local)
  93. (copy-recursively local output
  94. #:log (%make-void-port "w"))))
  95. ((%resolve-addresses) addresses output)
  96. (assembly-error "Could not resolve directory reference"))))
  97. ;; Disassembly
  98. (define (directory-ref-file? filename st)
  99. (eq? (stat:type st) 'directory))
  100. (define* (disassemble-directory-ref directory #:optional
  101. (algorithm (hash-algorithm sha256))
  102. #:key (name (basename directory)))
  103. (message "Disassembling the directory ~a" name)
  104. (let* ((addresses (file-addresses directory))
  105. (digest (file-digest directory algorithm))
  106. (cache (%disarchive-directory-cache))
  107. (local (and cache (digest->filename digest cache))))
  108. (when (and local (not (directory-exists? local)))
  109. (message "Saving directory in cache: ~a" local)
  110. (mkdir-p local)
  111. (copy-recursively directory local #:log (%make-void-port "w")))
  112. (make-directory-ref name addresses digest)))
  113. ;; Interfaces
  114. (define directory-ref-assembler
  115. (make-assembler directory-ref?
  116. directory-ref-name
  117. directory-ref-digest
  118. (const '())
  119. serialize-directory-ref
  120. serialized-directory-ref?
  121. deserialize-directory-ref
  122. assemble-directory-ref))
  123. (define directory-ref-disassembler
  124. (make-disassembler directory-ref-file?
  125. disassemble-directory-ref))