You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

167 lines
6.0 KiB

  1. ;;; GNU Guix --- Functional package management for GNU
  2. ;;; Copyright © 2012, 2013, 2015, 2016, 2017 Ludovic Courtès <ludo@gnu.org>
  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 scripts download)
  19. #:use-module (guix ui)
  20. #:use-module (guix scripts)
  21. #:use-module (guix store)
  22. #:use-module (gcrypt hash)
  23. #:use-module (guix base16)
  24. #:use-module (guix base32)
  25. #:use-module ((guix download) #:hide (url-fetch))
  26. #:use-module ((guix build download)
  27. #:select (url-fetch))
  28. #:use-module ((guix progress)
  29. #:select (current-terminal-columns))
  30. #:use-module ((guix build syscalls)
  31. #:select (terminal-columns))
  32. #:use-module (web uri)
  33. #:use-module (ice-9 match)
  34. #:use-module (srfi srfi-1)
  35. #:use-module (srfi srfi-26)
  36. #:use-module (srfi srfi-37)
  37. #:use-module (rnrs bytevectors)
  38. #:use-module (ice-9 binary-ports)
  39. #:export (guix-download))
  40. ;;;
  41. ;;; Command-line options.
  42. ;;;
  43. (define (download-to-file url file)
  44. "Download the file at URI to FILE. Return FILE."
  45. (let ((uri (string->uri url)))
  46. (match (uri-scheme uri)
  47. ((or 'file #f)
  48. (copy-file (uri-path uri) file))
  49. (_
  50. (url-fetch url file #:mirrors %mirrors)))
  51. file))
  52. (define* (download-to-store* url #:key (verify-certificate? #t))
  53. (with-store store
  54. (download-to-store store url
  55. #:verify-certificate? verify-certificate?)))
  56. (define %default-options
  57. ;; Alist of default option values.
  58. `((format . ,bytevector->nix-base32-string)
  59. (verify-certificate? . #t)
  60. (download-proc . ,download-to-store*)))
  61. (define (show-help)
  62. (display (G_ "Usage: guix download [OPTION] URL
  63. Download the file at URL to the store or to the given file, and print its
  64. file name and the hash of its contents.
  65. Supported formats: 'nix-base32' (default), 'base32', and 'base16'
  66. ('hex' and 'hexadecimal' can be used as well).\n"))
  67. (format #t (G_ "
  68. -f, --format=FMT write the hash in the given format"))
  69. (format #t (G_ "
  70. --no-check-certificate
  71. do not validate the certificate of HTTPS servers "))
  72. (format #f (G_ "
  73. -o, --output=FILE download to FILE"))
  74. (newline)
  75. (display (G_ "
  76. -h, --help display this help and exit"))
  77. (display (G_ "
  78. -V, --version display version information and exit"))
  79. (newline)
  80. (show-bug-report-information))
  81. (define %options
  82. ;; Specifications of the command-line options.
  83. (list (option '(#\f "format") #t #f
  84. (lambda (opt name arg result)
  85. (define fmt-proc
  86. (match arg
  87. ("nix-base32"
  88. bytevector->nix-base32-string)
  89. ("base32"
  90. bytevector->base32-string)
  91. ((or "base16" "hex" "hexadecimal")
  92. bytevector->base16-string)
  93. (x
  94. (leave (G_ "unsupported hash format: ~a~%") arg))))
  95. (alist-cons 'format fmt-proc
  96. (alist-delete 'format result))))
  97. (option '("no-check-certificate") #f #f
  98. (lambda (opt name arg result)
  99. (alist-cons 'verify-certificate? #f result)))
  100. (option '(#\o "output") #t #f
  101. (lambda (opt name arg result)
  102. (alist-cons 'download-proc
  103. (lambda* (url #:key verify-certificate?)
  104. (download-to-file url arg))
  105. (alist-delete 'download result))))
  106. (option '(#\h "help") #f #f
  107. (lambda args
  108. (show-help)
  109. (exit 0)))
  110. (option '(#\V "version") #f #f
  111. (lambda args
  112. (show-version-and-exit "guix download")))))
  113. ;;;
  114. ;;; Entry point.
  115. ;;;
  116. (define (guix-download . args)
  117. (define (parse-options)
  118. ;; Return the alist of option values.
  119. (args-fold* args %options
  120. (lambda (opt name arg result)
  121. (leave (G_ "~A: unrecognized option~%") name))
  122. (lambda (arg result)
  123. (when (assq 'argument result)
  124. (leave (G_ "~A: extraneous argument~%") arg))
  125. (alist-cons 'argument arg result))
  126. %default-options))
  127. (with-error-handling
  128. (let* ((opts (parse-options))
  129. (arg (or (assq-ref opts 'argument)
  130. (leave (G_ "no download URI was specified~%"))))
  131. (uri (or (string->uri arg)
  132. (false-if-exception
  133. (string->uri
  134. (string-append "file://" (canonicalize-path arg))))
  135. (leave (G_ "~a: failed to parse URI~%")
  136. arg)))
  137. (fetch (assq-ref opts 'download-proc))
  138. (path (parameterize ((current-terminal-columns
  139. (terminal-columns)))
  140. (fetch (uri->string uri)
  141. #:verify-certificate?
  142. (assq-ref opts 'verify-certificate?))))
  143. (hash (call-with-input-file
  144. (or path
  145. (leave (G_ "~a: download failed~%")
  146. arg))
  147. port-sha256))
  148. (fmt (assq-ref opts 'format)))
  149. (format #t "~a~%~a~%" path (fmt hash))
  150. #t)))