;;; GNU Guix --- Functional package management for GNU ;;; Copyright © 2022 Maxime Devos ;;; ;;; This file is part of GNU Guix. ;;; ;;; GNU Guix is free software; you can redistribute it and/or modify it ;;; under the terms of the GNU General Public License as published by ;;; the Free Software Foundation; either version 3 of the License, or (at ;;; your option) any later version. ;;; ;;; GNU Guix is distributed in the hope that it will be useful, but ;;; WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with GNU Guix. If not, see . (define-module (guix import latest-git) #:use-module (guix packages) #:use-module (guix upstream) #:use-module (guix ui) #:use-module (guix git) #:use-module (guix git-download) #:use-module (ice-9 match) #:use-module (srfi srfi-26) #:export (%latest-git-updater)) (define (check-valid-with-latest-git-commit? package value) "Verify that VALUE is a valid value for the 'with-latest-git-commit' package property of PACKAGE. If so, return #true. Otherwise, emit a warning and return #false. It is assumed VALUE is not false." (or (string? value) (eq? #true value) (begin (warning (or (package-field-location package 'properties) (package-location package)) (G_ "Package ~a has an invalid 'with-latest-git-commit' \ property.~%") (package-name package)) #false))) (define (with-latest-git-commit? package) "Return true if PACKAGE is hosted on a Git repository and it is requested that the latest Git commit is used even when not formally released." (match (package-source package) ((? origin? origin) (and (decompose-git-version (package-version package)) (eq? (origin-method origin) git-fetch) (git-reference? (origin-uri origin)) (and=> (assq-ref (package-properties package) 'with-latest-git-commit) (cut check-valid-with-latest-git-commit? package <>)))) (_ #f))) (define (latest-commit-reference-name package) "Return the name of the reference that is expected to hold the latest Git commit to use as source code." (match (assq-ref (package-properties package) 'with-latest-git-commit) ('#true "HEAD") ((? string? reference) reference))) (define (latest-git-upstream package) "Return an for the latest git commit of PACKAGE. If the reference pointing to the latest git commit has been deleted, return #false instead." (let* ((name (package-name package)) (old-version (package-version package)) (old-reference (origin-uri (package-source package))) (reference-name (latest-commit-reference-name package)) (commit (lookup-reference (git-reference-url old-reference) reference-name))) (if commit (upstream-source (package name) (version ;; See 'oid->commit' in (guix git) for why not string=?. ;; Don't increment the revision if the commit remains the same. (if (string-prefix? commit (git-reference-commit old-reference)) old-version (increment-git-version old-version commit))) (urls (git-reference (inherit old-reference) (commit commit)))) (begin (warning (package-location package) (G_ "Cannot update ~a because the reference ~a of ~a has \ disappeared.~%") (package-name package) reference-name (let ((maybe-hyperlink (if (supports-hyperlinks? (guix-warning-port)) hyperlink (lambda (x y) x))) (url (git-reference-url old-reference))) (maybe-hyperlink url url))) #false)))) (define %latest-git-updater (upstream-updater (name 'latest-git) (description "Updater for packages using latest Git commit") (pred with-latest-git-commit?) (latest latest-git-upstream)))