texlive.scm 7.3 KB

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