From 880916ac5228b9cfd6e65ac243d17f6bd12edaf9 Mon Sep 17 00:00:00 2001 From: Ludovic Courtès Date: Tue, 12 Mar 2019 15:50:13 +0100 Subject: guix build: Add '--with-git-url'. * guix/scripts/build.scm (%not-equal): New variable. (evaluate-git-replacement-specs): Use it instead of local variable 'not-equal'. (transform-package-source-git-url): New procedure. (%transformations): Add 'with-git-url'. (%transformation-options, show-transformation-options-help): Add '--with-git-url'. * tests/scripts-build.scm ("options->transformation, with-git-url"): New test. --- doc/guix.texi | 34 +++++++++++++++++++++++----------- guix/scripts/build.scm | 47 ++++++++++++++++++++++++++++++++++++++++------- tests/scripts-build.scm | 24 +++++++++++++++++++++++- 3 files changed, 86 insertions(+), 19 deletions(-) diff --git a/doc/guix.texi b/doc/guix.texi index 5bbd0ee7f0..139a09d1bc 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -7780,22 +7780,18 @@ must be compatible. If @var{replacement} is somehow incompatible with @var{package}, then the resulting package may be unusable. Use with care! -@item --with-branch=@var{package}=@var{branch} +@item --with-git-url=@var{package}=@var{url} @cindex Git, using the latest commit @cindex 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}. Git sub-modules of the repository are -fetched, recursively. +Build @var{package} from the latest commit of the @code{master} branch of the +Git repository at @var{url}. -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: +For example, the following commands builds the GNU C Library (glibc) straight +from its Git repository instead of building the currently-packaged release: @example -guix build --with-branch=guile-sqlite3=master cuirass +guix build glibc \ + --with-git-url=glibc=git://sourceware.org/git/glibc.git @end example @cindex continuous integration @@ -7809,6 +7805,22 @@ 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. +@item --with-branch=@var{package}=@var{branch} +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}. Git sub-modules of the repository are +fetched, recursively. + +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: + +@example +guix build --with-branch=guile-sqlite3=master cuirass +@end example + @item --with-commit=@var{package}=@var{commit} This is similar to @code{--with-branch}, except that it builds from @var{commit} rather than the tip of a branch. @var{commit} must be a valid diff --git a/guix/scripts/build.scm b/guix/scripts/build.scm index 6b29c470fb..5883dbfb44 100644 --- a/guix/scripts/build.scm +++ b/guix/scripts/build.scm @@ -272,16 +272,16 @@ (define (replacement-pair old new) (rewrite obj) obj)))) +(define %not-equal + (char-set-complement (char-set #\=))) + (define (evaluate-git-replacement-specs specs proc) "Parse SPECS, a list of strings like \"guile=stable-2.2\", and return a list of package pairs, where (PROC PACKAGE URL BRANCH-OR-COMMIT) returns the replacement package. 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) + (match (string-tokenize spec %not-equal) ((name branch-or-commit) (let* ((old (specification->package name)) (source (package-source old)) @@ -341,6 +341,33 @@ (define (replace old url commit) (rewrite obj) obj)))) +(define (transform-package-source-git-url replacement-specs) + "Return a procedure that, when passed a package, replaces its dependencies +according to REPLACEMENT-SPECS. REPLACEMENT-SPECS is a list of strings like +\"guile-json=https://gitthing.com/…\" meaning that packages are built using +a checkout of the Git repository at the given URL." + ;; FIXME: Currently this cannot be combined with '--with-branch' or + ;; '--with-commit' because they all transform "from scratch". + (define replacements + (map (lambda (spec) + (match (string-tokenize spec %not-equal) + ((name url) + (let* ((old (specification->package name)) + (new (package + (inherit old) + (source (git-checkout (url url) + (recursive? #t)))))) + (cons old new))))) + replacement-specs)) + + (define 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 @@ -350,7 +377,8 @@ (define %transformations (with-input . ,transform-package-inputs) (with-graft . ,transform-package-inputs/graft) (with-branch . ,transform-package-source-branch) - (with-commit . ,transform-package-source-commit))) + (with-commit . ,transform-package-source-commit) + (with-git-url . ,transform-package-source-git-url))) (define %transformation-options ;; The command-line interface to the above transformations. @@ -368,7 +396,9 @@ (define %transformation-options (option '("with-branch") #t #f (parser 'with-branch)) (option '("with-commit") #t #f - (parser 'with-commit))))) + (parser 'with-commit)) + (option '("with-git-url") #t #f + (parser 'with-git-url))))) (define (show-transformation-options-help) (display (G_ " @@ -385,7 +415,10 @@ (define (show-transformation-options-help) build PACKAGE from the latest commit of BRANCH")) (display (G_ " --with-commit=PACKAGE=COMMIT - build PACKAGE from COMMIT"))) + build PACKAGE from COMMIT")) + (display (G_ " + --with-git-url=PACKAGE=URL + build PACKAGE from the repository at URL"))) (define (options->transformation opts) diff --git a/tests/scripts-build.scm b/tests/scripts-build.scm index 190426ed06..54681274b9 100644 --- a/tests/scripts-build.scm +++ b/tests/scripts-build.scm @@ -1,5 +1,5 @@ ;;; GNU Guix --- Functional package management for GNU -;;; Copyright © 2016, 2017 Ludovic Courtès +;;; Copyright © 2016, 2017, 2019 Ludovic Courtès ;;; ;;; This file is part of GNU Guix. ;;; @@ -23,6 +23,7 @@ (define-module (test-scripts-build) #:use-module (guix scripts build) #:use-module (guix ui) #:use-module (guix utils) + #:use-module (guix git) #:use-module (gnu packages) #:use-module (gnu packages base) #:use-module (gnu packages busybox) @@ -164,4 +165,25 @@ (define-module (test-scripts-build) ((("x" dep)) (eq? (package-replacement dep) findutils))))))))))) +(test-equal "options->transformation, with-git-url" + (let ((source (git-checkout (url "https://example.org") + (recursive? #t)))) + (list source source)) + (let* ((p (dummy-package "guix.scm" + (inputs `(("foo" ,grep) + ("bar" ,(dummy-package "chbouib" + (native-inputs `(("x" ,grep))))))))) + (t (options->transformation '((with-git-url . "grep=https://example.org"))))) + (with-store store + (let ((new (t store p))) + (and (not (eq? new p)) + (match (package-inputs new) + ((("foo" dep1) ("bar" dep2)) + (and (string=? (package-full-name dep1) + (package-full-name grep)) + (string=? (package-name dep2) "chbouib") + (match (package-native-inputs dep2) + ((("x" dep3)) + (map package-source (list dep1 dep3)))))))))))) + (test-end) -- cgit v1.2.3