[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[bug#33522] [PATCH 3/3] guix build: Add '--with-branch' transformation o

From: Ludovic Courtès
Subject: [bug#33522] [PATCH 3/3] guix build: Add '--with-branch' transformation option.
Date: Tue, 27 Nov 2018 16:34:02 +0100

From: Ludovic Courtès <address@hidden>

* guix/scripts/build.scm (evaluate-git-replacement-specs)
(transform-package-source-branch): New procedures.
(%transformations, %transformation-options): Add 'with-branch'.
(show-transformation-options-help): Likewise.
* tests/ New file.
* (SH_TESTS): Add it.
* doc/guix.texi (Package Transformation Options): Document it.
---                |  1 +
 doc/guix.texi              | 27 ++++++++++++++++++
 guix/scripts/build.scm     | 56 ++++++++++++++++++++++++++++++++++++--
 tests/ | 48 ++++++++++++++++++++++++++++++++
 4 files changed, 129 insertions(+), 3 deletions(-)
 create mode 100644 tests/

diff --git a/ b/
index c5676b0b94..4f134ab174 100644
--- a/
+++ b/
@@ -407,6 +407,7 @@ endif
 SH_TESTS =                                     \
   tests/                          \
+  tests/                   \
   tests/                       \
   tests/                             \
   tests/                           \
diff --git a/doc/guix.texi b/doc/guix.texi
index 917a3e9d57..18bc3508c1 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -6447,6 +6447,33 @@ must be compatible.  If @var{replacement} is somehow 
incompatible with
 @var{package}, then the resulting package may be unusable.  Use with
address@hidden address@hidden@var{branch}
address@hidden Git, using the latest commit
address@hidden latest commit, building
+Build @var{package} from the latest commit of @var{branch}.  The @code{source}
+field of @var{package} must be an origin with the @code{git-fetch} method
+(@pxref{origin Reference}) or a @code{git-checkout} object; the repository URL
+is taken from that @code{source}.
+For instance, the following command builds @code{guile-sqlite3} from the
+latest commit of its @code{master} branch, and then builds @code{guix} (which
+depends on it) and @code{cuirass} (which depends on @code{guix}) against this
+specific @code{guile-sqlite3} build:
+guix build --with-branch=guile-sqlite3=master cuirass
address@hidden example
address@hidden continuous integration
+Obviously, since it uses the latest commit of the given branch, the result of
+such a command varies over time.  Nevertheless it is a convenient way to
+rebuild entire software stacks against the latest commit of one or more
+packages.  This is particularly useful in the context of continuous
+integration (CI).
+Checkouts are kept in a cache under @file{~/.cache/guix/checkouts} to speed up
+consecutive accesses to the same repository.  You may want to clean it up once
+in a while to save disk space.
 @end table
 @node Additional Build Options
diff --git a/guix/scripts/build.scm b/guix/scripts/build.scm
index 13978abb77..e8f2fe973d 100644
--- a/guix/scripts/build.scm
+++ b/guix/scripts/build.scm
@@ -45,6 +45,8 @@
   #:use-module (srfi srfi-37)
   #:autoload   (gnu packages) (specification->package %package-module-path)
   #:autoload   (guix download) (download-to-store)
+  #:autoload   (guix git-download) (git-reference?)
+  #:autoload   (guix git) (git-checkout?)
   #:use-module (guix status)
   #:use-module ((guix progress) #:select (current-terminal-columns))
   #:use-module ((guix build syscalls) #:select (terminal-columns))
@@ -270,6 +272,48 @@ current 'gnutls' package, after which version 3.5.4 is 
grafted onto them."
           (rewrite obj)
+(define (evaluate-git-replacement-specs specs)
+  "Parse SPECS, a list of strings like \"guile=stable-2.2\", and return a list
+of package pairs.  Raise an error if an element of SPECS uses invalid syntax,
+or if a package it refers to could not be found."
+  (define not-equal
+    (char-set-complement (char-set #\=)))
+  (map (lambda (spec)
+         (match (string-tokenize spec not-equal)
+           ((name branch)
+            (let* ((old    (specification->package name))
+                   (source (package-source old))
+                   (url    (cond ((and (origin? source)
+                                       (git-reference? (origin-uri source)))
+                                  (git-reference-url (origin-uri source)))
+                                 ((git-checkout? source)
+                                  (git-checkout-url source))
+                                 (else
+                                  (leave (G_ "the source of ~a is not a Git \
+                                         (package-full-name old))))))
+              (cons old
+                    (package
+                      (inherit old)
+                      (version (string-append "git." branch))
+                      (source (git-checkout (url url) (branch branch)))))))
+           (x
+            (leave (G_ "invalid replacement specification: ~s~%") spec))))
+       specs))
+(define (transform-package-source-branch replacement-specs)
+  "Return a procedure that, when passed a package, replaces its direct
+dependencies according to REPLACEMENT-SPECS.  REPLACEMENT-SPECS is a list of
+strings like \"guile-next=stable-3.0\" meaning that packages are built using
+'guile-next' from the latest commit on its 'stable-3.0' branch."
+  (let* ((replacements (evaluate-git-replacement-specs replacement-specs))
+         (rewrite      (package-input-rewriting replacements)))
+    (lambda (store obj)
+      (if (package? obj)
+          (rewrite obj)
+          obj))))
 (define %transformations
   ;; Transformations that can be applied to things to build.  The car is the
   ;; key used in the option alist, and the cdr is the transformation
@@ -277,7 +321,8 @@ current 'gnutls' package, after which version 3.5.4 is 
grafted onto them."
   ;; things to build.
   `((with-source . ,transform-package-source)
     (with-input  . ,transform-package-inputs)
-    (with-graft  . ,transform-package-inputs/graft)))
+    (with-graft  . ,transform-package-inputs/graft)
+    (with-branch . ,transform-package-source-branch)))
 (define %transformation-options
   ;; The command-line interface to the above transformations.
@@ -291,7 +336,9 @@ current 'gnutls' package, after which version 3.5.4 is 
grafted onto them."
           (option '("with-input") #t #f
                   (parser 'with-input))
           (option '("with-graft") #t #f
-                  (parser 'with-graft)))))
+                  (parser 'with-graft))
+          (option '("with-branch") #t #f
+                  (parser 'with-branch)))))
 (define (show-transformation-options-help)
   (display (G_ "
@@ -302,7 +349,10 @@ current 'gnutls' package, after which version 3.5.4 is 
grafted onto them."
                          replace dependency PACKAGE by REPLACEMENT"))
   (display (G_ "
-                         graft REPLACEMENT on packages that refer to 
+                         graft REPLACEMENT on packages that refer to PACKAGE"))
+    (display (G_ "
+      --with-branch=PACKAGE=BRANCH
+                         build PACKAGE from the latest commit of BRANCH")))
 (define (options->transformation opts)
diff --git a/tests/ b/tests/
new file mode 100644
index 0000000000..bc50d9c0ef
--- /dev/null
+++ b/tests/
@@ -0,0 +1,48 @@
+# GNU Guix --- Functional package management for GNU
+# Copyright © 2018 Ludovic Courtès <address@hidden>
+# 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
+# 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 <>.
+# Test 'guix build --with-branch'.
+guix build --version
+# 'guix build --with-branch' requires access to the network to clone the
+# Git repository below.
+if ! guile -c '(getaddrinfo "" "80" AI_NUMERICSERV)' 2> /dev/null
+    # Skipping.
+    exit 77
+orig_drv="`guix build guile-gcrypt -d`"
+latest_drv="`guix build guile-gcrypt --with-branch=guile-gcrypt=master -d`"
+test -n "$latest_drv"
+test "$orig_drv" != "$latest_drv"
+# FIXME: '-S' currently doesn't work with non-derivation source.
+# checkout="`guix build guile-gcrypt --with-branch=guile-gcrypt=master -S`"
+checkout="`guix gc --references "$latest_drv" | grep guile-gcrypt | grep -v -E 
+test -d "$checkout"
+test -f "$checkout/COPYING"
+orig_drv="`guix build guix -d`"
+latest_drv="`guix build guix --with-branch=guile-gcrypt=master -d`"
+guix gc -R "$latest_drv" | grep guile-gcrypt-git.master
+test "$orig_drv" != "$latest_drv"

reply via email to

[Prev in Thread] Current Thread [Next in Thread]