json.scm 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. ;;; GNU Guix --- Functional package management for GNU
  2. ;;; Copyright © 2014 David Thompson <davet@gnu.org>
  3. ;;; Copyright © 2015, 2016 Eric Bavier <bavier@member.fsf.org>
  4. ;;; Copyright © 2018, 2019 Ludovic Courtès <ludo@gnu.org>
  5. ;;; Copyright © 2020 Ricardo Wurmus <rekado@elephly.net>
  6. ;;;
  7. ;;; This file is part of GNU Guix.
  8. ;;;
  9. ;;; GNU Guix is free software; you can redistribute it and/or modify it
  10. ;;; under the terms of the GNU General Public License as published by
  11. ;;; the Free Software Foundation; either version 3 of the License, or (at
  12. ;;; your option) any later version.
  13. ;;;
  14. ;;; GNU Guix is distributed in the hope that it will be useful, but
  15. ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
  16. ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. ;;; GNU General Public License for more details.
  18. ;;;
  19. ;;; You should have received a copy of the GNU General Public License
  20. ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
  21. (define-module (guix import json)
  22. #:use-module (json)
  23. #:use-module (guix http-client)
  24. #:use-module (guix import utils)
  25. #:use-module (guix import print)
  26. #:use-module (ice-9 match)
  27. #:use-module (ice-9 rdelim)
  28. #:use-module (srfi srfi-1)
  29. #:use-module (srfi srfi-2)
  30. #:use-module (srfi srfi-26)
  31. #:use-module (srfi srfi-34)
  32. #:export (json-fetch
  33. json->code
  34. json->scheme-file))
  35. (define* (json-fetch url
  36. ;; Note: many websites returns 403 if we omit a
  37. ;; 'User-Agent' header.
  38. #:key (headers `((user-agent . "GNU Guile")
  39. (Accept . "application/json"))))
  40. "Return a representation of the JSON resource URL (a list or hash table), or
  41. #f if URL returns 403 or 404. HEADERS is a list of HTTP headers to pass in
  42. the query."
  43. (guard (c ((and (http-get-error? c)
  44. (let ((error (http-get-error-code c)))
  45. (or (= 403 error)
  46. (= 404 error))))
  47. #f))
  48. (let* ((port (http-fetch url #:headers headers))
  49. (result (json->scm port)))
  50. (close-port port)
  51. result)))
  52. (define (json->code file-name)
  53. "Read FILE-NAME containing one ore more JSON package definitions and return
  54. a list of S-expressions, or return #F when the JSON is invalid."
  55. (catch 'json-invalid
  56. (lambda ()
  57. (let ((json (json-string->scm
  58. (with-input-from-file file-name read-string))))
  59. (match json
  60. (#(packages ...)
  61. ;; To allow definitions to refer to one another, collect references
  62. ;; to local definitions and tell alist->package to ignore them.
  63. (second
  64. (memq #:result
  65. (fold
  66. (lambda (pkg names+result)
  67. (match names+result
  68. ((#:names names #:result result)
  69. (list #:names
  70. (cons (assoc-ref pkg "name") names)
  71. #:result
  72. (append result
  73. (list
  74. (package->code (alist->package pkg names))
  75. (string->symbol (assoc-ref pkg "name"))))))))
  76. (list #:names '()
  77. #:result '())
  78. packages))))
  79. (package
  80. (list (package->code (alist->package json))
  81. (string->symbol (assoc-ref json "name")))))))
  82. (const #f)))
  83. (define (json->scheme-file file)
  84. "Convert the FILE containing a JSON package definition to a Scheme
  85. representation and return the new file name (or #F on error)."
  86. (and-let* ((sexprs (json->code file))
  87. (file* (let* ((tempdir (or (getenv "TMPDIR") "/tmp"))
  88. (template (string-append tempdir "/guix-XXXXXX"))
  89. (port (mkstemp! template)))
  90. (close-port port)
  91. template)))
  92. (call-with-output-file file*
  93. (lambda (port)
  94. (write '(use-modules (gnu)
  95. (guix)
  96. ((guix licenses) #:prefix license:))
  97. port)
  98. (for-each (cut write <> port) sexprs)))
  99. file*))