executable_guix-latest 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  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, 2024 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 format)
  18. #:use-module (ice-9 match)
  19. #:use-module (ice-9 popen)
  20. #:use-module (ice-9 pretty-print)
  21. #:use-module (ice-9 rdelim)
  22. #:use-module (srfi srfi-1)
  23. #:use-module (srfi srfi-37)
  24. #:autoload (guix openpgp) (openpgp-format-fingerprint)
  25. #:export (main))
  26. ;;; Commentary:
  27. ;;;
  28. ;;; Example:
  29. ;;; guix-latest --channels=/home/alice/channels-current.scm /home/alice/src/guix/gnu/system/examples/bare-bones.tmpl
  30. ;;;
  31. ;;; Code:
  32. (define %options
  33. (let ((display-and-exit-proc (lambda (msg)
  34. (lambda (opt name arg loads)
  35. (display msg) (quit)))))
  36. (list (option '(#\v "version") #f #f
  37. (display-and-exit-proc "guix-latest version 0.0.1\n"))
  38. (option '(#\C "channels") #t #f
  39. (lambda (opt name arg result)
  40. (alist-cons 'channel-file arg result)))
  41. (option '(#\n "dry-run") #f #f
  42. (lambda (opt name arg result)
  43. (alist-cons 'dry-run? #t result)))
  44. (option '(#\N "without-substitutes") #f #f
  45. (lambda (opt name arg result)
  46. (alist-cons 'without-substitutes? #t result)))
  47. (option '(#\F "local-file") #f #f
  48. (lambda (opt name arg result)
  49. (alist-cons 'local-file? #t result)))
  50. (option '(#\L "load-path") #f #t
  51. (lambda (opt name arg loads)
  52. (alist-cons 'load-path arg loads)))
  53. (option '(#\h "help") #f #f
  54. (display-and-exit-proc
  55. "Usage: guix-latest ...")))))
  56. (define %default-options
  57. '())
  58. (define %home
  59. (and=> (getenv "HOME")
  60. (lambda (home)
  61. home)))
  62. (define (main args)
  63. (define (load-channels file)
  64. (let ((result (load* file (make-user-module '((guix channels))))))
  65. (if (and (list? result) (every channel? result))
  66. result
  67. (leave (G_ "'~a' did not return a list of channels~%") file))))
  68. (define opts
  69. (args-fold (cdr (program-arguments))
  70. %options
  71. (lambda (opt name arg loads)
  72. (error "Unrecognized option `~A'" name))
  73. (lambda (op loads)
  74. (cons op loads))
  75. %default-options))
  76. (define local-file?
  77. (assoc-ref opts 'local-file?))
  78. (define channels
  79. (cons (cond ((assoc-ref opts 'without-substitutes?)
  80. %default-guix-channel)
  81. (local-file?
  82. (channel
  83. (inherit %default-guix-channel)
  84. (url "https://cgit.wugi.info/git/guix/guix")))
  85. (else (channel-with-substitutes-available
  86. %default-guix-channel
  87. "http://ci.guix.gnu.org.wugi.info")))
  88. (map (lambda (channel)
  89. (match-record channel (@@ (guix channels) <channel>)
  90. (name url introduction)
  91. (if introduction
  92. ((@ (guix channels) channel)
  93. (name name)
  94. (url url)
  95. (introduction introduction))
  96. ((@ (guix channels) channel)
  97. (name name)
  98. (url url)))))
  99. (filter (lambda (channel)
  100. (not (string= (symbol->string (channel-name channel)) "guix")))
  101. (channel-list opts)))))
  102. (define store
  103. (open-connection))
  104. (define cached
  105. (cached-channel-instance store
  106. channels
  107. #:authenticate? (not local-file?)
  108. #:cache-directory (%inferior-cache-directory)
  109. #:ttl (* 3600 24 30)))
  110. (define inferior
  111. (open-inferior cached #:error-port (current-error-port)))
  112. (define (file->store-path file)
  113. (inferior-eval
  114. `(begin
  115. (use-modules (guix profiles)
  116. (guix ui))
  117. (define %store (open-connection))
  118. (format (current-error-port) "Loading `~a'.~%" ,file)
  119. (let ((load-path ,(assoc-ref opts 'load-path)))
  120. (when load-path
  121. (add-to-load-path load-path)))
  122. (define file-derivation
  123. (run-with-store %store
  124. (let ((definition (load* ,file (make-user-module '()))))
  125. (cond ((operating-system? definition)
  126. (operating-system-derivation definition))
  127. (((@@ (guix profiles) manifest?) definition)
  128. (profile-derivation definition #:allow-collisions? #t))
  129. (else #f)))))
  130. (if (build-derivations %store (list file-derivation))
  131. `(list ,(derivation->output-path file-derivation)
  132. ,@(map (@@ (gnu services) channel->code)
  133. (sort ((@@ (guix describe) current-channels))
  134. (lambda (c1 c2)
  135. (string< (symbol->string ((@ (guix channels) channel-name) c1))
  136. (symbol->string ((@ (guix channels) channel-name) c2)))))))
  137. #f))
  138. inferior))
  139. (define outputs
  140. (map file->store-path (filter string? opts)))
  141. (define channel-file
  142. (assoc-ref opts 'channel-file))
  143. (for-each
  144. (match-lambda
  145. ((list drv channels ...)
  146. (display drv)
  147. (newline)
  148. (let ((display-channels (lambda ()
  149. (pretty-print `(list ,@channels)))))
  150. (if (assoc-ref opts 'dry-run?)
  151. (display-channels)
  152. (begin
  153. (with-output-to-file channel-file
  154. (lambda ()
  155. (display-channels))))))))
  156. outputs)
  157. (system* "git" "add" channel-file)
  158. (system* "git" "commit"
  159. (format #f "--message=Update ~a." channel-file)))
  160. ;;; guix-latest ends here