executable_guix-latest 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. #!/run/current-system/profile/bin/guile \
  2. --no-auto-compile -e (guix-latest) -s
  3. !#
  4. ;;;; guix-latest --- Build Guix system with latest channels.
  5. ;;;; Copyright © 2021, 2022, 2023 Oleg Pykhalov <go.wigust@gmail.com>
  6. ;;;; Released under the GNU GPLv3 or any later version.
  7. (define-module (guix-latest)
  8. #:use-module (gnu system)
  9. #:use-module (guix channels)
  10. #:use-module (guix ci)
  11. #:use-module (guix inferior)
  12. #:use-module (guix profiles)
  13. #:use-module (guix records)
  14. #:use-module (guix scripts pull)
  15. #:use-module (guix store)
  16. #:use-module (guix ui)
  17. #:use-module (ice-9 match)
  18. #:use-module (ice-9 pretty-print)
  19. #:use-module (srfi srfi-1)
  20. #:use-module (srfi srfi-37)
  21. #:autoload (guix openpgp) (openpgp-format-fingerprint)
  22. #:export (main))
  23. ;;; Commentary:
  24. ;;;
  25. ;;; Example:
  26. ;;; guix-latest --channels=/home/alice/channels-current.scm /home/alice/src/guix/gnu/system/examples/bare-bones.tmpl
  27. ;;;
  28. ;;; Code:
  29. (define %options
  30. (let ((display-and-exit-proc (lambda (msg)
  31. (lambda (opt name arg loads)
  32. (display msg) (quit)))))
  33. (list (option '(#\v "version") #f #f
  34. (display-and-exit-proc "guix-latest version 0.0.1\n"))
  35. (option '(#\C "channels") #t #f
  36. (lambda (opt name arg result)
  37. (alist-cons 'channel-file arg result)))
  38. (option '(#\n "dry-run") #f #f
  39. (lambda (opt name arg result)
  40. (alist-cons 'dry-run? #t result)))
  41. (option '(#\N "without-substitutes") #f #f
  42. (lambda (opt name arg result)
  43. (alist-cons 'without-substitutes? #t result)))
  44. (option '(#\L "load-path") #f #t
  45. (lambda (opt name arg loads)
  46. (alist-cons 'load-path arg loads)))
  47. (option '(#\h "help") #f #f
  48. (display-and-exit-proc
  49. "Usage: guix-latest ...")))))
  50. (define %default-options
  51. '())
  52. (define (main args)
  53. (define (load-channels file)
  54. (let ((result (load* file (make-user-module '((guix channels))))))
  55. (if (and (list? result) (every channel? result))
  56. result
  57. (leave (G_ "'~a' did not return a list of channels~%") file))))
  58. (define opts
  59. (args-fold (cdr (program-arguments))
  60. %options
  61. (lambda (opt name arg loads)
  62. (error "Unrecognized option `~A'" name))
  63. (lambda (op loads)
  64. (cons op loads))
  65. %default-options))
  66. (define channels
  67. (cons (if (assoc-ref opts 'without-substitutes?)
  68. %default-guix-channel
  69. (channel-with-substitutes-available
  70. %default-guix-channel
  71. "http://ci.guix.gnu.org.wugi.info"))
  72. (map (lambda (channel)
  73. (match-record channel (@@ (guix channels) <channel>)
  74. (name url introduction)
  75. (if introduction
  76. ((@ (guix channels) channel)
  77. (name name)
  78. (url url)
  79. (introduction introduction))
  80. ((@ (guix channels) channel)
  81. (name name)
  82. (url url)))))
  83. (filter (lambda (channel)
  84. (not (string= (symbol->string (channel-name channel)) "guix")))
  85. (channel-list opts)))))
  86. (define store
  87. (open-connection))
  88. (define cached
  89. (cached-channel-instance store
  90. channels
  91. #:authenticate? #t
  92. #:cache-directory (%inferior-cache-directory)
  93. #:ttl (* 3600 24 30)))
  94. (define inferior
  95. (open-inferior cached #:error-port (current-error-port)))
  96. (define (file->store-path file)
  97. (inferior-eval
  98. `(begin
  99. (use-modules (guix profiles)
  100. (guix ui))
  101. (define %store (open-connection))
  102. (format (current-error-port) "Loading `~a'.~%" ,file)
  103. (let ((load-path ,(assoc-ref opts 'load-path)))
  104. (when load-path
  105. (add-to-load-path load-path)))
  106. (define file-derivation
  107. (run-with-store %store
  108. (let ((definition (load* ,file (make-user-module '()))))
  109. (cond ((operating-system? definition)
  110. (operating-system-derivation definition))
  111. (((@@ (guix profiles) manifest?) definition)
  112. (profile-derivation definition #:allow-collisions? #t))
  113. (else #f)))))
  114. (if (build-derivations %store (list file-derivation))
  115. `(list ,(derivation->output-path file-derivation)
  116. ,@(map (@@ (gnu services) channel->code)
  117. (sort ((@@ (guix describe) current-channels))
  118. (lambda (c1 c2)
  119. (string< (symbol->string ((@ (guix channels) channel-name) c1))
  120. (symbol->string ((@ (guix channels) channel-name) c2)))))))
  121. #f))
  122. inferior))
  123. (define outputs
  124. (map file->store-path (filter string? opts)))
  125. (for-each
  126. (match-lambda
  127. ((list drv channels ...)
  128. (display drv)
  129. (newline)
  130. (let ((display-channels (lambda ()
  131. (pretty-print `(list ,@channels)))))
  132. (if (assoc-ref opts 'dry-run?)
  133. (display-channels)
  134. (with-output-to-file (assoc-ref opts 'channel-file)
  135. (lambda ()
  136. (display-channels)))))))
  137. outputs))
  138. ;;; guix-latest ends here