assemblers.scm 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. ;;; Disarchive
  2. ;;; Copyright © 2020, 2021, 2023 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)
  19. #:use-module (disarchive digests)
  20. #:use-module (disarchive logging)
  21. #:use-module (ice-9 exceptions)
  22. #:use-module (ice-9 match)
  23. #:use-module (srfi srfi-1)
  24. #:use-module (srfi srfi-9)
  25. #:use-module (srfi srfi-26)
  26. #:export (<assembler>
  27. make-assembler
  28. assembler?
  29. assembler-x?
  30. assembler-x-name
  31. assembler-x-digest
  32. assembler-x-inputs
  33. assembler-serialize-x
  34. assembler-serialized-x?
  35. assembler-deserialize-x
  36. assembler-assemble-x
  37. &assembly-error
  38. make-assembly-error
  39. assembly-error?
  40. assembly-error
  41. blueprint-name
  42. blueprint-digest
  43. blueprint-inputs
  44. serialize-blueprint
  45. deserialize-blueprint
  46. assemble))
  47. ;;; Commentary:
  48. ;;;
  49. ;;; This module provides a generalized interface for blueprints. A
  50. ;;; blueprint is an object that describes how to produce an output
  51. ;;; that matches its digest. Blueprints can also be serialized and
  52. ;;; deserialized.
  53. ;;;
  54. ;;; Code:
  55. (define-record-type <assembler>
  56. (make-assembler x? x-name x-digest x-inputs
  57. serialize-x serialized-x? deserialize-x
  58. assemble-x)
  59. assembler?
  60. (x? assembler-x?)
  61. (x-name assembler-x-name)
  62. (x-digest assembler-x-digest)
  63. (x-inputs assembler-x-inputs)
  64. (serialize-x assembler-serialize-x)
  65. (serialized-x? assembler-serialized-x?)
  66. (deserialize-x assembler-deserialize-x)
  67. (assemble-x assembler-assemble-x))
  68. (define-exception-type &assembly-error &error
  69. make-assembly-error
  70. assembly-error?)
  71. (define-syntax-rule (assembly-error msg)
  72. (raise-exception (make-exception (make-assembly-error)
  73. (make-exception-with-message msg))))
  74. (define (name->assembler name)
  75. (let ((module `(disarchive assemblers ,name)))
  76. (module-ref (resolve-interface module)
  77. (symbol-append name '-assembler))))
  78. (define %assemblers
  79. (delay (map name->assembler
  80. '(gzip-member
  81. xz-file
  82. bzip2-stream
  83. tarball
  84. directory-ref))))
  85. (define (blueprint-assembler blueprint)
  86. "Get the assembler for BLUEPRINT."
  87. (or (find (lambda (asm) ((assembler-x? asm) blueprint))
  88. (force %assemblers))
  89. (error "No assembler for blueprint")))
  90. (define (serialized-assembler sexp)
  91. "Get the assembler for SEXP."
  92. (or (find (lambda (asm) ((assembler-serialized-x? asm) sexp))
  93. (force %assemblers))
  94. (error "No assembler for serialized object")))
  95. (define (blueprint-name blueprint)
  96. "Get the name of BLUEPRINT."
  97. (match-let ((($ <assembler> x? x-name _ _ _ _ _ _)
  98. (blueprint-assembler blueprint)))
  99. (x-name blueprint)))
  100. (define (blueprint-digest blueprint)
  101. "Get the digest of BLUEPRINT."
  102. (match-let ((($ <assembler> x? _ x-digest _ _ _ _ _)
  103. (blueprint-assembler blueprint)))
  104. (x-digest blueprint)))
  105. (define (blueprint-inputs blueprint)
  106. "Get the inputs of BLUEPRINT."
  107. (match-let ((($ <assembler> x? _ _ x-inputs _ _ _ _)
  108. (blueprint-assembler blueprint)))
  109. (x-inputs blueprint)))
  110. (define (serialize-blueprint blueprint)
  111. "Serialize BLUEPRINT."
  112. (match-let ((($ <assembler> x? _ _ _ serialize-x _ _ _)
  113. (blueprint-assembler blueprint)))
  114. (serialize-x blueprint)))
  115. (define (deserialize-blueprint sexp)
  116. "Deserialize SEXP into a blueprint."
  117. (match-let ((($ <assembler> _ _ _ _ _ serialized-x? deserialize-x _)
  118. (serialized-assembler sexp)))
  119. (deserialize-x sexp)))
  120. (define* (assemble blueprint workspace #:key (verify? #t))
  121. (match-let ((($ <assembler> x? x-name _ _ _ _ _ assemble-x)
  122. (blueprint-assembler blueprint)))
  123. (let* ((name (x-name blueprint))
  124. (digest (blueprint-digest blueprint))
  125. (out (digest->filename digest workspace)))
  126. (unless (and (file-exists? out) (file-digest? out digest))
  127. (for-each (cut assemble <> workspace)
  128. (blueprint-inputs blueprint))
  129. (assemble-x blueprint workspace)
  130. (when verify?
  131. (start-message "Checking ~a digest... " name)
  132. (if (file-digest? out digest)
  133. (message "ok")
  134. (begin
  135. (message "fail")
  136. (assembly-error "Output is incorrect"))))))))