texlive.scm 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. ;;; GNU Guix --- Functional package management for GNU
  2. ;;; Copyright © 2017 Ricardo Wurmus <rekado@elephly.net>
  3. ;;;
  4. ;;; This file is part of GNU Guix.
  5. ;;;
  6. ;;; GNU Guix is free software; you can redistribute it and/or modify it
  7. ;;; under the terms of the GNU General Public License as published by
  8. ;;; the Free Software Foundation; either version 3 of the License, or (at
  9. ;;; your option) any later version.
  10. ;;;
  11. ;;; GNU Guix is distributed in the hope that it will be useful, but
  12. ;;; 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 GNU Guix. If not, see <http://www.gnu.org/licenses/>.
  18. (define-module (guix import texlive)
  19. #:use-module (ice-9 match)
  20. #:use-module (sxml simple)
  21. #:use-module (sxml xpath)
  22. #:use-module (srfi srfi-11)
  23. #:use-module (srfi srfi-1)
  24. #:use-module (srfi srfi-26)
  25. #:use-module (srfi srfi-34)
  26. #:use-module (web uri)
  27. #:use-module (guix http-client)
  28. #:use-module (gcrypt hash)
  29. #:use-module (guix memoization)
  30. #:use-module (guix store)
  31. #:use-module (guix base32)
  32. #:use-module (guix serialization)
  33. #:use-module (guix svn-download)
  34. #:use-module (guix import utils)
  35. #:use-module (guix utils)
  36. #:use-module (guix upstream)
  37. #:use-module (guix packages)
  38. #:use-module (gnu packages)
  39. #:use-module (guix build-system texlive)
  40. #:export (texlive->guix-package
  41. fetch-sxml
  42. sxml->package))
  43. ;;; Commentary:
  44. ;;;
  45. ;;; Generate a package declaration template for the latest version of a
  46. ;;; package on CTAN, using the XML output produced by the XML API to the CTAN
  47. ;;; database at http://www.ctan.org/xml/1.2/
  48. ;;;
  49. ;;; Instead of taking the packages from CTAN, however, we fetch the sources
  50. ;;; from the SVN repository of the Texlive project. We do this because CTAN
  51. ;;; only keeps a single version of each package whereas we can access any
  52. ;;; version via SVN. Unfortunately, this means that the importer is really
  53. ;;; just a Texlive importer, not a generic CTAN importer.
  54. ;;;
  55. ;;; Code:
  56. (define string->license
  57. (match-lambda
  58. ("artistic2" 'gpl3+)
  59. ("gpl" 'gpl3+)
  60. ("gpl1" 'gpl1)
  61. ("gpl1+" 'gpl1+)
  62. ("gpl2" 'gpl2)
  63. ("gpl2+" 'gpl2+)
  64. ("gpl3" 'gpl3)
  65. ("gpl3+" 'gpl3+)
  66. ("lgpl2.1" 'lgpl2.1)
  67. ("lgpl3" 'lgpl3)
  68. ("knuth" 'knuth)
  69. ("pd" 'public-domain)
  70. ("bsd2" 'bsd-2)
  71. ("bsd3" 'bsd-3)
  72. ("bsd4" 'bsd-4)
  73. ("opl" 'opl1.0+)
  74. ("ofl" 'silofl1.1)
  75. ("lppl" 'lppl)
  76. ("lppl1" 'lppl1.0+) ; usually means "or later"
  77. ("lppl1.2" 'lppl1.2+) ; usually means "or later"
  78. ("lppl1.3" 'lppl1.3+) ; usually means "or later"
  79. ("lppl1.3a" 'lppl1.3a)
  80. ("lppl1.3b" 'lppl1.3b)
  81. ("lppl1.3c" 'lppl1.3c)
  82. ("cc-by-2" 'cc-by-2.0)
  83. ("cc-by-3" 'cc-by-3.0)
  84. ("cc-by-sa-2" 'cc-by-sa2.0)
  85. ("cc-by-sa-3" 'cc-by-sa3.0)
  86. ("mit" 'expat)
  87. ("fdl" 'fdl1.3+)
  88. ("gfl" 'gfl1.0)
  89. ;; These are known non-free licenses
  90. ("noinfo" 'unknown)
  91. ("nosell" 'non-free)
  92. ("shareware" 'non-free)
  93. ("nosource" 'non-free)
  94. ("nocommercial" 'non-free)
  95. ("cc-by-nc-nd-1" 'non-free)
  96. ("cc-by-nc-nd-2" 'non-free)
  97. ("cc-by-nc-nd-2.5" 'non-free)
  98. ("cc-by-nc-nd-3" 'non-free)
  99. ("cc-by-nc-nd-4" 'non-free)
  100. ((x) (string->license x))
  101. ((lst ...) `(list ,@(map string->license lst)))
  102. (_ #f)))
  103. (define (fetch-sxml name)
  104. "Return an sxml representation of the package information contained in the
  105. XML description of the CTAN package or #f in case of failure."
  106. ;; This API always returns the latest release of the module.
  107. (let ((url (string-append "http://www.ctan.org/xml/1.2/pkg/" name)))
  108. (guard (c ((http-get-error? c)
  109. (format (current-error-port)
  110. "error: failed to retrieve package information \
  111. from ~s: ~a (~s)~%"
  112. (uri->string (http-get-error-uri c))
  113. (http-get-error-code c)
  114. (http-get-error-reason c))
  115. #f))
  116. (xml->sxml (http-fetch url)
  117. #:trim-whitespace? #t))))
  118. (define (guix-name component name)
  119. "Return a Guix package name for a given Texlive package NAME."
  120. (string-append "texlive-" component "-"
  121. (string-map (match-lambda
  122. (#\_ #\-)
  123. (#\. #\-)
  124. (chr (char-downcase chr)))
  125. name)))
  126. (define* (sxml->package sxml #:optional (component "latex"))
  127. "Return the `package' s-expression for a Texlive package from the SXML
  128. expression describing it."
  129. (define (sxml-value path)
  130. (match ((sxpath path) sxml)
  131. (() #f)
  132. ((val) val)))
  133. (with-store store
  134. (let* ((id (sxml-value '(entry @ id *text*)))
  135. (synopsis (sxml-value '(entry caption *text*)))
  136. (version (or (sxml-value '(entry version @ number *text*))
  137. (sxml-value '(entry version @ date *text*))))
  138. (license (match ((sxpath '(entry license @ type *text*)) sxml)
  139. ((license) (string->license license))
  140. ((lst ...) (map string->license lst))))
  141. (home-page (string-append "http://www.ctan.org/pkg/" id))
  142. (ref (texlive-ref component id))
  143. (checkout (download-svn-to-store store ref)))
  144. `(package
  145. (name ,(guix-name component id))
  146. (version ,version)
  147. (source (origin
  148. (method svn-fetch)
  149. (uri (texlive-ref ,component ,id))
  150. (sha256
  151. (base32
  152. ,(bytevector->nix-base32-string
  153. (let-values (((port get-hash) (open-sha256-port)))
  154. (write-file checkout port)
  155. (force-output port)
  156. (get-hash)))))))
  157. (build-system texlive-build-system)
  158. (arguments ,`(,'quote (#:tex-directory ,(string-join (list component id) "/"))))
  159. (home-page ,home-page)
  160. (synopsis ,synopsis)
  161. (description ,(string-trim-both
  162. (string-join
  163. (map string-trim-both
  164. (string-split
  165. (beautify-description
  166. (sxml->string (or (sxml-value '(entry description))
  167. '())))
  168. #\newline)))))
  169. (license ,(match license
  170. ((lst ...) `(list ,@lst))
  171. (license license)))))))
  172. (define texlive->guix-package
  173. (memoize
  174. (lambda* (package-name #:optional (component "latex"))
  175. "Fetch the metadata for PACKAGE-NAME from REPO and return the `package'
  176. s-expression corresponding to that package, or #f on failure."
  177. (and=> (fetch-sxml package-name)
  178. (cut sxml->package <> component)))))
  179. ;;; ctan.scm ends here