[PATCH] guix: Add --with-dependency-source option

OpenSubmitted by Jesse Gibbons.
Details
2 participants
  • Jesse Gibbons
  • Ludovic Courtès
Owner
unassigned
Severity
normal
J
J
Jesse Gibbons wrote on 4 Sep 2020 06:30
(name . Guix Patches)(address . guix-patches@gnu.org)
9c3a00ba-19bf-a8e9-8803-d150e91f1b6e@gmail.com
    The attached patch adds support for the --with-dependency-source
common build option. It can be used to specify the sources of
dependencies of specified packages. With this step, we can close #42155.
This is also a step in closing #43061.

Note that I suggested making a new
--with-dependency-source=package=source build option in response to
#42155 and nobody responded with an objection. So I am sending this
patch with the assumption that there are no objections to this new build
option, and that if a member of the community wants to completely
replace the behavior of --with-source with the behavior of the new
option, that person can do the work required to not break
--with-source=source.

-Jesse
From 91a89277067fd454ad77edb3a09ed06382f3694c Mon Sep 17 00:00:00 2001
From: Jesse Gibbons <jgibbons2357+guix@gmail.com>
Date: Thu, 3 Sep 2020 17:45:08 -0600
Subject: [PATCH v1 1/1] guix: Add --with-dependency-source option

* guix/scripts/build.scm: (transform-package-inputs/source): new
function
(evaluate-source-replacement-specs): new function
(%transformations): add with-dependency-source option
(%transformation-options): add with-dependency-source-option
(show-transformation-options-help): document --with-dependency-source
---
guix/scripts/build.scm | 39 +++++++++++++++++++++++++++++++++++++++
1 file changed, 39 insertions(+)

Toggle diff (80 lines)
diff --git a/guix/scripts/build.scm b/guix/scripts/build.scm
index 6286a43c02..0713595a00 100644
--- a/guix/scripts/build.scm
+++ b/guix/scripts/build.scm
@@ -280,6 +280,24 @@ current 'gnutls' package, after which version 3.5.4 is grafted onto them."
           (rewrite obj)
           obj))))
 
+(define (transform-package-inputs/source 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=/path/to/source\" or
+\"guile=https://www.example.com/guile-source.tar.gz\" meaning that, any
+dependency on a package called \"guile\" must be replaced with a dependency on a
+\"guile\" built with the source at the specified location."
+  (lambda (store obj)
+    (let* ((replacements (evaluate-source-replacement-specs replacement-specs
+                                                            (lambda (old url)
+                                                              (package-with-source store old url))))
+           (rewrite (package-input-rewriting/spec replacements))
+           (rewrite* (lambda (obj)
+                       (rewrite obj))))
+      (if (package? obj)
+          (rewrite* obj)
+          obj))))
+
 (define %not-equal
   (char-set-complement (char-set #\=)))
 
@@ -314,6 +332,21 @@ syntax, or if a package it refers to could not be found."
             (leave (G_ "invalid replacement specification: ~s~%") spec))))
        specs))
 
+(define (evaluate-source-replacement-specs specs proc)
+  "Parse SPECS, a list of strings like \"guile=/path/to/source\", and return a
+list of package pairs, where (PROC PACKAGE URL) 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."
+  (map (lambda (spec)
+         (match (string-tokenize spec %not-equal)
+           ((spec url)
+            (define (replace old)
+              (proc old url))
+            (cons spec replace))
+           (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
@@ -399,6 +432,7 @@ a checkout of the Git repository at the given URL."
   ;; procedure; it is called with two arguments: the store, and a list of
   ;; things to build.
   `((with-source . ,transform-package-source)
+    (with-dependency-source . ,transform-package-inputs/source)
     (with-input  . ,transform-package-inputs)
     (with-graft  . ,transform-package-inputs/graft)
     (with-branch . ,transform-package-source-branch)
@@ -414,6 +448,8 @@ a checkout of the Git repository at the given URL."
                            rest)))))
     (list (option '("with-source") #t #f
                   (parser 'with-source))
+          (option '("with-dependency-source") #t #f
+                  (parser 'with-dependency-source))
           (option '("with-input") #t #f
                   (parser 'with-input))
           (option '("with-graft") #t #f
@@ -429,6 +465,9 @@ a checkout of the Git repository at the given URL."
   (display (G_ "
       --with-source=SOURCE
                          use SOURCE when building the corresponding package"))
+  (display (G_ "
+      --with-dependency-source=PACKAGE=SOURCE
+                         use SOURCE when building the corresponding dependency package"))
   (display (G_ "
       --with-input=PACKAGE=REPLACEMENT
                          replace dependency PACKAGE by REPLACEMENT"))
-- 
2.28.0
L
L
Ludovic Courtès wrote on 10 Sep 2020 11:43
(name . Jesse Gibbons)(address . jgibbons2357@gmail.com)(address . 43193@debbugs.gnu.org)
87y2lige5l.fsf@gnu.org
Hi Jesse,

Jesse Gibbons <jgibbons2357@gmail.com> skribis:

Toggle quote (5 lines)
>     The attached patch adds support for the --with-dependency-source
> common build option. It can be used to specify the sources of
> dependencies of specified packages. With this step, we can close
> #42155. This is also a step in closing #43061.

Excellent!

Toggle quote (9 lines)
> Note that I suggested making a new
> --with-dependency-source=package=source build option in response to
> #42155 and nobody responded with an objection. So I am sending this
> patch with the assumption that there are no objections to this new
> build option, and that if a member of the community wants to
> completely replace the behavior of --with-source with the behavior of
> the new option, that person can do the work required to not break
> --with-source=source.

OK. Like I wrote at https://issues.guix.gnu.org/42155#3, I wouldn’t
mind simply calling this new option ‘--with-source’. What we’d lose by
doing so is the warning you get if you do
‘--with-source=does-not-exist=whatever’, saying the option had no
effect, but that’s about it. The new ‘--with-source’ behavior
(recursive) would be consistent with the other options, which, to me, is
more important.

WDYT?

Toggle quote (12 lines)
>>From 91a89277067fd454ad77edb3a09ed06382f3694c Mon Sep 17 00:00:00 2001
> From: Jesse Gibbons <jgibbons2357+guix@gmail.com>
> Date: Thu, 3 Sep 2020 17:45:08 -0600
> Subject: [PATCH v1 1/1] guix: Add --with-dependency-source option
>
> * guix/scripts/build.scm: (transform-package-inputs/source): new
> function
> (evaluate-source-replacement-specs): new function
> (%transformations): add with-dependency-source option
> (%transformation-options): add with-dependency-source-option
> (show-transformation-options-help): document --with-dependency-source

[...]

Toggle quote (13 lines)
> +(define (evaluate-source-replacement-specs specs proc)
> + "Parse SPECS, a list of strings like \"guile=/path/to/source\", and return a
> +list of package pairs, where (PROC PACKAGE URL) 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."
> + (map (lambda (spec)
> + (match (string-tokenize spec %not-equal)
> + ((spec url)
> + (define (replace old)
> + (proc old url))
> + (cons spec replace))
> + (x
> + (leave (G_ "invalid replacement specification: ~s~%") spec))))
^
Add “source” here. It’s always a good idea to not have the exact same
error message in several places. :-)

Could you:

1. adjust doc/guix.texi accordingly? That is, if we rename this new
option to ‘--with-source’, simply add a note stating that it’s
recursive.

2. add a test to tests/guix-build.sh? There are already --with-source
tests in other files. You can mimic them, essentially to make sure
the option has an effect.

3. optionally add an entry as a separate commit to
etc/news.scm. I can do that for you if you want.

Thanks!

Ludo’.
J
J
Jesse Gibbons wrote on 11 Sep 2020 07:16
(name . Ludovic Courtès)(address . ludo@gnu.org)(address . 43193@debbugs.gnu.org)
7f52c72f-c280-b585-d1ad-ca012f804910@gmail.com
On 9/10/20 3:43 AM, Ludovic Courtès wrote:
Toggle quote (25 lines)
> Hi Jesse,
>
> Jesse Gibbons <jgibbons2357@gmail.com> skribis:
>
>>     The attached patch adds support for the --with-dependency-source
>> common build option. It can be used to specify the sources of
>> dependencies of specified packages. With this step, we can close
>> #42155. This is also a step in closing #43061.
> Excellent!
>
>> Note that I suggested making a new
>> --with-dependency-source=package=source build option in response to
>> #42155 and nobody responded with an objection. So I am sending this
>> patch with the assumption that there are no objections to this new
>> build option, and that if a member of the community wants to
>> completely replace the behavior of --with-source with the behavior of
>> the new option, that person can do the work required to not break
>> --with-source=source.
> OK. Like I wrote at <https://issues.guix.gnu.org/42155#3>, I wouldn’t
> mind simply calling this new option ‘--with-source’. What we’d lose by
> doing so is the warning you get if you do
> ‘--with-source=does-not-exist=whatever’, saying the option had no
> effect, but that’s about it. The new ‘--with-source’ behavior
> (recursive) would be consistent with the other options, which, to me, is
> more important.
I agree that '--with-source' is a better name for the option, but I
don't want to lose that particular functionality. I worked a little more
to alter "--with-source" while still preserving the simple
'--with-source=source' option, because once it's committed to master, it
will be difficult to turn back and get the ideal implementation. The
result is a bit dirty and should be refactored and cleaned, but at least
it works. Attached is the updated patch.
Toggle quote (32 lines)
>
> WDYT?
>
>> >From 91a89277067fd454ad77edb3a09ed06382f3694c Mon Sep 17 00:00:00 2001
>> From: Jesse Gibbons <jgibbons2357+guix@gmail.com>
>> Date: Thu, 3 Sep 2020 17:45:08 -0600
>> Subject: [PATCH v1 1/1] guix: Add --with-dependency-source option
>>
>> * guix/scripts/build.scm: (transform-package-inputs/source): new
>> function
>> (evaluate-source-replacement-specs): new function
>> (%transformations): add with-dependency-source option
>> (%transformation-options): add with-dependency-source-option
>> (show-transformation-options-help): document --with-dependency-source
> [...]
>
>> +(define (evaluate-source-replacement-specs specs proc)
>> + "Parse SPECS, a list of strings like \"guile=/path/to/source\", and return a
>> +list of package pairs, where (PROC PACKAGE URL) 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."
>> + (map (lambda (spec)
>> + (match (string-tokenize spec %not-equal)
>> + ((spec url)
>> + (define (replace old)
>> + (proc old url))
>> + (cons spec replace))
>> + (x
>> + (leave (G_ "invalid replacement specification: ~s~%") spec))))
> ^
> Add “source” here. It’s always a good idea to not have the exact same
> error message in several places. :-)
Fixed.
Toggle quote (5 lines)
> Could you:
>
> 1. adjust doc/guix.texi accordingly? That is, if we rename this new
> option to ‘--with-source’, simply add a note stating that it’s
> recursive.
I included this in the attached patch.
Toggle quote (6 lines)
> 2. add a test to tests/guix-build.sh? There are already --with-source
> tests in other files. You can mimic them, essentially to make sure
> the option has an effect.
> 3. optionally add an entry as a separate commit to
> etc/news.scm. I can do that for you if you want.
>
Do you still think the tests should be updated and this change should be
announced in the news file? I'm willing to do these.
Toggle quote (3 lines)
> Thanks!
>
> Ludo’.
-Jesse
From 2786da1e7011c59f08fc150dfa284f35bc0ed093 Mon Sep 17 00:00:00 2001
From: Jesse Gibbons <jgibbons2357+guix@gmail.com>
Date: Thu, 3 Sep 2020 17:45:08 -0600
Subject: [PATCH 1/1] guix: Make --with-source option recursive

* guix/scripts/build.scm: (transform-package-inputs/source): new
function
(evaluate-source-replacement-specs): new function
(%transformations): change with-source to use
evaluate-source-replacement-specs

*doc/guix.texi (Package Transformation Options): Document it.
---
doc/guix.texi | 3 ++-
guix/scripts/build.scm | 39 ++++++++++++++++++++++++++++++++++++++-
2 files changed, 40 insertions(+), 2 deletions(-)

Toggle diff (80 lines)
diff --git a/doc/guix.texi b/doc/guix.texi
index 1d6782e6fa..4036861c23 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -9129,7 +9129,8 @@ without having to type in the definitions of package variants
 @itemx --with-source=@var{package}=@var{source}
 @itemx --with-source=@var{package}@@@var{version}=@var{source}
 Use @var{source} as the source of @var{package}, and @var{version} as
-its version number.
+its version number.  This replacement is applied recursively on all
+dependencies only if PACKAGE is specified.
 @var{source} must be a file name or a URL, as for @command{guix
 download} (@pxref{Invoking guix download}).
 
diff --git a/guix/scripts/build.scm b/guix/scripts/build.scm
index 6286a43c02..095457b174 100644
--- a/guix/scripts/build.scm
+++ b/guix/scripts/build.scm
@@ -280,6 +280,28 @@ current 'gnutls' package, after which version 3.5.4 is grafted onto them."
           (rewrite obj)
           obj))))
 
+(define (transform-package-inputs/source 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=/path/to/source\" or
+\"guile=https://www.example.com/guile-source.tar.gz\" meaning that, any
+dependency on a package called \"guile\" must be replaced with a dependency on a
+\"guile\" built with the source at the specified location."
+  (match (string-tokenize (car replacement-specs) %not-equal)
+    ((spec url)
+     (lambda (store obj)
+       (let* ((replacements (evaluate-source-replacement-specs replacement-specs
+                                                               (lambda (old url)
+                                                                 (package-with-source store old url))))
+              (rewrite (package-input-rewriting/spec replacements))
+              (rewrite* (lambda (obj)
+                          (rewrite obj))))
+         (if (package? obj)
+             (rewrite* obj)
+             obj))))
+    ((url)
+     (transform-package-source replacement-specs))))
+
 (define %not-equal
   (char-set-complement (char-set #\=)))
 
@@ -314,6 +336,21 @@ syntax, or if a package it refers to could not be found."
             (leave (G_ "invalid replacement specification: ~s~%") spec))))
        specs))
 
+(define (evaluate-source-replacement-specs specs proc)
+  "Parse SPECS, a list of strings like \"guile=/path/to/source\", and return a
+list of package pairs, where (PROC PACKAGE URL) 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."
+  (map (lambda (spec)
+         (match (string-tokenize spec %not-equal)
+           ((spec url)
+            (define (replace old)
+              (proc old url))
+            (cons spec replace))
+           (x
+            (leave (G_ "invalid source 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
@@ -398,7 +435,7 @@ a checkout of the Git repository at the given URL."
   ;; key used in the option alist, and the cdr is the transformation
   ;; procedure; it is called with two arguments: the store, and a list of
   ;; things to build.
-  `((with-source . ,transform-package-source)
+  `((with-source . ,transform-package-inputs/source)
     (with-input  . ,transform-package-inputs)
     (with-graft  . ,transform-package-inputs/graft)
     (with-branch . ,transform-package-source-branch)
-- 
2.28.0
L
L
Ludovic Courtès wrote on 11 Sep 2020 17:43
(name . Jesse Gibbons)(address . jgibbons2357@gmail.com)(address . 43193@debbugs.gnu.org)
87wo10s4j6.fsf@gnu.org
Hi,

Jesse Gibbons <jgibbons2357@gmail.com> skribis:

Toggle quote (15 lines)
>> Could you:
>>
>> 1. adjust doc/guix.texi accordingly? That is, if we rename this new
>> option to ‘--with-source’, simply add a note stating that it’s
>> recursive.
> I included this in the attached patch.
>> 2. add a test to tests/guix-build.sh? There are already --with-source
>> tests in other files. You can mimic them, essentially to make sure
>> the option has an effect.
>> 3. optionally add an entry as a separate commit to
>> etc/news.scm. I can do that for you if you want.
>>
> Do you still think the tests should be updated and this change should
> be announced in the news file? I'm willing to do these.

Yes, please. There’s should be a test that checks that --with-source
works for non-leaf packages. A new entry would also be nice.

Toggle quote (13 lines)
> From 2786da1e7011c59f08fc150dfa284f35bc0ed093 Mon Sep 17 00:00:00 2001
> From: Jesse Gibbons <jgibbons2357+guix@gmail.com>
> Date: Thu, 3 Sep 2020 17:45:08 -0600
> Subject: [PATCH 1/1] guix: Make --with-source option recursive
>
> * guix/scripts/build.scm: (transform-package-inputs/source): new
> function
> (evaluate-source-replacement-specs): new function
> (%transformations): change with-source to use
> evaluate-source-replacement-specs
>
> *doc/guix.texi (Package Transformation Options): Document it.

Nitpick: There are spacing and capitalization issues. Please see ‘git
log’ for examples.

Toggle quote (9 lines)
> +++ b/doc/guix.texi
> @@ -9129,7 +9129,8 @@ without having to type in the definitions of package variants
> @itemx --with-source=@var{package}=@var{source}
> @itemx --with-source=@var{package}@@@var{version}=@var{source}
> Use @var{source} as the source of @var{package}, and @var{version} as
> -its version number.
> +its version number. This replacement is applied recursively on all
> +dependencies only if PACKAGE is specified.

s/PACKAGE/@var{package}/

However, the semantics are a bit “weird”. I would just do the recursive
replacement thing unconditionally. WDYT?

Toggle quote (10 lines)
> +(define (transform-package-inputs/source 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=/path/to/source\" or
> +\"guile=https://www.example.com/guile-source.tar.gz\" meaning that, any
> +dependency on a package called \"guile\" must be replaced with a dependency on a
> +\"guile\" built with the source at the specified location."
> + (match (string-tokenize (car replacement-specs) %not-equal)
> + ((spec url)

s/url/file/ since it’s a file name.

Toggle quote (13 lines)
> + (lambda (store obj)
> + (let* ((replacements (evaluate-source-replacement-specs replacement-specs
> + (lambda (old url)
> + (package-with-source store old url))))
> + (rewrite (package-input-rewriting/spec replacements))
> + (rewrite* (lambda (obj)
> + (rewrite obj))))
> + (if (package? obj)
> + (rewrite* obj)
> + obj))))
> + ((url)
> + (transform-package-source replacement-specs))))

So maybe drop the second clause for non-recursive replacement, and drop
‘transform-package-source’ as well.

Thanks!

Ludo’.
J
J
Jesse Gibbons wrote on 11 Sep 2020 20:28
(name . Ludovic Courtès)(address . ludo@gnu.org)(address . 43193@debbugs.gnu.org)
4c890f8c-539c-1c9c-f558-7ba01cffa480@gmail.com
On 9/11/20 9:43 AM, Ludovic Courtès wrote:
Toggle quote (20 lines)
> Hi,
>
> Jesse Gibbons <jgibbons2357@gmail.com> skribis:
>
>>> Could you:
>>>
>>> 1. adjust doc/guix.texi accordingly? That is, if we rename this new
>>> option to ‘--with-source’, simply add a note stating that it’s
>>> recursive.
>> I included this in the attached patch.
>>> 2. add a test to tests/guix-build.sh? There are already --with-source
>>> tests in other files. You can mimic them, essentially to make sure
>>> the option has an effect.
>>> 3. optionally add an entry as a separate commit to
>>> etc/news.scm. I can do that for you if you want.
>>>
>> Do you still think the tests should be updated and this change should
>> be announced in the news file? I'm willing to do these.
> Yes, please. There’s should be a test that checks that --with-source
> works for non-leaf packages. A new entry would also be nice.
I will work on that then.
Toggle quote (15 lines)
>
>> From 2786da1e7011c59f08fc150dfa284f35bc0ed093 Mon Sep 17 00:00:00 2001
>> From: Jesse Gibbons <jgibbons2357+guix@gmail.com>
>> Date: Thu, 3 Sep 2020 17:45:08 -0600
>> Subject: [PATCH 1/1] guix: Make --with-source option recursive
>>
>> * guix/scripts/build.scm: (transform-package-inputs/source): new
>> function
>> (evaluate-source-replacement-specs): new function
>> (%transformations): change with-source to use
>> evaluate-source-replacement-specs
>>
>> *doc/guix.texi (Package Transformation Options): Document it.
> Nitpick: There are spacing and capitalization issues. Please see ‘git
> log’ for examples.
I'll fix this.
Toggle quote (38 lines)
>> +++ b/doc/guix.texi
>> @@ -9129,7 +9129,8 @@ without having to type in the definitions of package variants
>> @itemx --with-source=@var{package}=@var{source}
>> @itemx --with-source=@var{package}@@@var{version}=@var{source}
>> Use @var{source} as the source of @var{package}, and @var{version} as
>> -its version number.
>> +its version number. This replacement is applied recursively on all
>> +dependencies only if PACKAGE is specified.
> s/PACKAGE/@var{package}/
>
> However, the semantics are a bit “weird”. I would just do the recursive
> replacement thing unconditionally. WDYT?
>
>> +(define (transform-package-inputs/source 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=/path/to/source\" or
>> +\"guile=https://www.example.com/guile-source.tar.gz\" meaning that, any
>> +dependency on a package called \"guile\" must be replaced with a dependency on a
>> +\"guile\" built with the source at the specified location."
>> + (match (string-tokenize (car replacement-specs) %not-equal)
>> + ((spec url)
> s/url/file/ since it’s a file name.
>
>> + (lambda (store obj)
>> + (let* ((replacements (evaluate-source-replacement-specs replacement-specs
>> + (lambda (old url)
>> + (package-with-source store old url))))
>> + (rewrite (package-input-rewriting/spec replacements))
>> + (rewrite* (lambda (obj)
>> + (rewrite obj))))
>> + (if (package? obj)
>> + (rewrite* obj)
>> + obj))))
>> + ((url)
>> + (transform-package-source replacement-specs))))
> So maybe drop the second clause for non-recursive replacement, and drop
> ‘transform-package-source’ as well.
I included a fallback to transform-package-source because the following
happens:

$ ./pre-inst-env guix build --with-source=$(guix build --source hello) hello
guix build: error: invalid source replacement specification:
"/gnu/store/hbdalsf5lpf01x4dcknwx6xbn6n5km6k-hello-2.10.tar.gz"

This does not fail when I fall back to the non-recursive logic.

I can drop transform-package-source, but I will need to do some more
hacking to figure out how the package name and version are parsed from
the file name as described in the manual, and move it to the logic in
transform-package-inputs/source. I'm not going to have as much free time
starting next week, so I might not be able to do that for a while, but I
will try to get it done ASAP.

Toggle quote (4 lines)
>
> Thanks!
>
> Ludo’.
L
L
Ludovic Courtès wrote on 13 Sep 2020 14:55
(name . Jesse Gibbons)(address . jgibbons2357@gmail.com)(address . 43193@debbugs.gnu.org)
87y2ld7s5b.fsf@gnu.org
Hi,

Jesse Gibbons <jgibbons2357@gmail.com> skribis:

Toggle quote (2 lines)
> On 9/11/20 9:43 AM, Ludovic Courtès wrote:

[...]

Toggle quote (16 lines)
>> So maybe drop the second clause for non-recursive replacement, and drop
>> ‘transform-package-source’ as well.
> I included a fallback to transform-package-source because the
> following happens:
>
> $ ./pre-inst-env guix build --with-source=$(guix build --source hello) hello
> guix build: error: invalid source replacement specification:
> "/gnu/store/hbdalsf5lpf01x4dcknwx6xbn6n5km6k-hello-2.10.tar.gz"
>
> This does not fail when I fall back to the non-recursive logic.
>
> I can drop transform-package-source, but I will need to do some more
> hacking to figure out how the package name and version are parsed from
> the file name as described in the manual, and move it to the logic in
> transform-package-inputs/source.

Yes, that’d be nice. Namely, if you do:

guix build hello --source=hello-1.2.3.tar.gz

it should work just as now (from the source file name, we assume that
the source applies to package “hello”).

Conversely, doing:

guix build hello --source=xyz-hello-1.2.3.tar.gz

would have no effect. It would not even emit a warning, unlike now.

Toggle quote (4 lines)
> I'm not going to have as much free time starting next week, so I might
> not be able to do that for a while, but I will try to get it done
> ASAP.

Sure, let’s stay in touch, I think we’re almost done!

Thank you,
Ludo’.
J
J
Jesse Gibbons wrote on 13 Sep 2020 16:28
(name . Ludovic Courtès)(address . ludo@gnu.org)(address . 43193@debbugs.gnu.org)
9130ce2d-4d10-0aa5-ad68-b312097fcb4a@gmail.com
On 9/13/20 6:55 AM, Ludovic Courtès wrote:
Toggle quote (34 lines)
> Hi,
>
> Jesse Gibbons <jgibbons2357@gmail.com> skribis:
>
>> On 9/11/20 9:43 AM, Ludovic Courtès wrote:
> [...]
>
>>> So maybe drop the second clause for non-recursive replacement, and drop
>>> ‘transform-package-source’ as well.
>> I included a fallback to transform-package-source because the
>> following happens:
>>
>> $ ./pre-inst-env guix build --with-source=$(guix build --source hello) hello
>> guix build: error: invalid source replacement specification:
>> "/gnu/store/hbdalsf5lpf01x4dcknwx6xbn6n5km6k-hello-2.10.tar.gz"
>>
>> This does not fail when I fall back to the non-recursive logic.
>>
>> I can drop transform-package-source, but I will need to do some more
>> hacking to figure out how the package name and version are parsed from
>> the file name as described in the manual, and move it to the logic in
>> transform-package-inputs/source.
> Yes, that’d be nice. Namely, if you do:
>
> guix build hello --source=hello-1.2.3.tar.gz
>
> it should work just as now (from the source file name, we assume that
> the source applies to package “hello”).
>
> Conversely, doing:
>
> guix build hello --source=xyz-hello-1.2.3.tar.gz
>
> would have no effect. It would not even emit a warning, unlike now.
I was able to get this working nicely.
Toggle quote (5 lines)
>> I'm not going to have as much free time starting next week, so I might
>> not be able to do that for a while, but I will try to get it done
>> ASAP.
> Sure, let’s stay in touch, I think we’re almost done!

I wrote a new test that checks non-leafs. The following tests fail:

test-name: options->transformation, no transformations
test-name: options->transformation, with-source
test-name: options->transformation, with-source, replacement
test-name: options->transformation, with-source, with version
test-name: options->transformation, with-source, no matches
test-name: options->transformation, with-source, PKG@VER=URI

Some of these tests raise a similar error, some only have a false actual
value, and "options->transformation, with-source, no matches" will need
to be changed at the test level because it checks for a warning in the
output. I've been trying to debug, but the tests don't even give a stack
trace. I will do what I can to fix the tests and follow up at the end of
the week.

-Jesse
J
J
Jesse Gibbons wrote on 27 Sep 2020 00:46
(name . Ludovic Courtès)(address . ludo@gnu.org)(address . 43193@debbugs.gnu.org)
9c60e5f2-e9fa-55c9-863f-cc3bccc2cf15@gmail.com
Attached are the patches that make the --with-source option recursive,
add documentation, add a test, adjust a test, and update the news.

As expected, the changes I made are incompatible with the test
"options->transformation, with-source, no matches". Since
options->transformation, with-source does a recursive replacement, it
returns a clone of the package in question. I have tried changing the
comparison to eq?, eqv? and equal?, each returning false, so I settled
on a (limited) comparison of the packages' attributes.

On 9/13/20 6:55 AM, Ludovic Courtès wrote:
Toggle quote (42 lines)
> Hi,
>
> Jesse Gibbons <jgibbons2357@gmail.com> skribis:
>
>> On 9/11/20 9:43 AM, Ludovic Courtès wrote:
> [...]
>
>>> So maybe drop the second clause for non-recursive replacement, and drop
>>> ‘transform-package-source’ as well.
>> I included a fallback to transform-package-source because the
>> following happens:
>>
>> $ ./pre-inst-env guix build --with-source=$(guix build --source hello) hello
>> guix build: error: invalid source replacement specification:
>> "/gnu/store/hbdalsf5lpf01x4dcknwx6xbn6n5km6k-hello-2.10.tar.gz"
>>
>> This does not fail when I fall back to the non-recursive logic.
>>
>> I can drop transform-package-source, but I will need to do some more
>> hacking to figure out how the package name and version are parsed from
>> the file name as described in the manual, and move it to the logic in
>> transform-package-inputs/source.
> Yes, that’d be nice. Namely, if you do:
>
> guix build hello --source=hello-1.2.3.tar.gz
>
> it should work just as now (from the source file name, we assume that
> the source applies to package “hello”).
>
> Conversely, doing:
>
> guix build hello --source=xyz-hello-1.2.3.tar.gz
>
> would have no effect. It would not even emit a warning, unlike now.
>
>> I'm not going to have as much free time starting next week, so I might
>> not be able to do that for a while, but I will try to get it done
>> ASAP.
> Sure, let’s stay in touch, I think we’re almost done!
>
> Thank you,
> Ludo’.
From 2d2f6c97ad1deeb2fc8a214d992c7894a7c5e293 Mon Sep 17 00:00:00 2001
From: Jesse Gibbons <jgibbons2357+guix@gmail.com>
Date: Thu, 3 Sep 2020 17:45:08 -0600
Subject: [PATCH 1/2] guix: Make --with-source option recursive

* guix/scripts/build.scm: (transform-package-inputs/source): new
function
(evaluate-source-replacement-specs): new function
(%transformations): change with-source to use
evaluate-source-replacement-specs

* doc/guix.texi (Package Transformation Options): document it.

* tests/scripts-build.scm: (options->transformation, with-source, no
matches): adjust to new expectations.
(options->transformation, with-source, recursive): new test.
---
doc/guix.texi | 4 +--
guix/scripts/build.scm | 61 ++++++++++++++++++++++++++++++++++++++---
tests/scripts-build.scm | 25 +++++++++++++++--
3 files changed, 81 insertions(+), 9 deletions(-)

Toggle diff (153 lines)
diff --git a/doc/guix.texi b/doc/guix.texi
index 82241b010a..3470ccc99c 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -9142,8 +9142,8 @@ without having to type in the definitions of package variants
 @itemx --with-source=@var{package}=@var{source}
 @itemx --with-source=@var{package}@@@var{version}=@var{source}
 Use @var{source} as the source of @var{package}, and @var{version} as
-its version number.
-@var{source} must be a file name or a URL, as for @command{guix
+its version number.  This replacement is applied recursively on all
+dependencies.  @var{source} must be a file name or a URL, as for @command{guix
 download} (@pxref{Invoking guix download}).
 
 When @var{package} is omitted,
diff --git a/guix/scripts/build.scm b/guix/scripts/build.scm
index 38e0516c95..a899f18a61 100644
--- a/guix/scripts/build.scm
+++ b/guix/scripts/build.scm
@@ -201,9 +201,9 @@ matching URIs given in SOURCES."
              (#f
               ;; Determine the package name and version from URI.
               (call-with-values
-                  (lambda ()
-                    (hyphen-package-name->name+version
-                     (tarball-base-name (basename uri))))
+                (lambda ()
+                 (hyphen-package-name->name+version
+                  (tarball-base-name (basename uri))))
                 (lambda (name version)
                   (list name version uri))))
              (index
@@ -280,6 +280,26 @@ current 'gnutls' package, after which version 3.5.4 is grafted onto them."
           (rewrite obj)
           obj))))
 
+(define (transform-package-inputs/source 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=/path/to/source\" or
+\"guile=https://www.example.com/guile-source.tar.gz\" meaning that, any
+dependency on a package called \"guile\" must be replaced with a dependency on a
+\"guile\" built with the source at the specified location.  SPECS may also
+simply be a file location, in which case the package name and version are parsed
+from the file name."
+ (lambda (store obj)
+   (let* ((replacements (evaluate-source-replacement-specs replacement-specs
+                                                           (lambda* (old file #:optional version)
+                                                           (package-with-source store old file version))))
+          (rewrite (package-input-rewriting/spec replacements))
+          (rewrite* (lambda (obj)
+                     (rewrite obj))))
+         (if (package? obj)
+             (rewrite* obj)
+             obj))))
+
 (define %not-equal
   (char-set-complement (char-set #\=)))
 
@@ -314,6 +334,39 @@ syntax, or if a package it refers to could not be found."
             (leave (G_ "invalid replacement specification: ~s~%") spec))))
        specs))
 
+(define (evaluate-source-replacement-specs specs proc)
+  "Parse SPECS, a list of strings like \"guile=/path/to/source\", and return a
+list of package pairs, where (PROC PACKAGE URL) 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* (replacement file #:optional version)
+   (lambda (old)
+               (proc old file version)))
+  (map (lambda (spec)
+         (match (string-tokenize spec %not-equal)
+           ((package-spec file)
+            (let* ((spec-list (call-with-values
+                                (lambda ()
+                                  (package-specification->name+version+output package-spec))
+                                list))
+                   (name (list-ref spec-list 0))
+                   (version (list-ref spec-list 1)))
+              (cons name (replacement file version))))
+           ((file)
+             (let* ((package-spec
+              (call-with-values
+                (lambda ()
+                 (hyphen-package-name->name+version
+                  (tarball-base-name (basename file))))
+                (lambda (name version)
+                              (cons name version))))
+              (name (car package-spec))
+              (version (cdr package-spec)))
+               (cons name (replacement file version))))
+           (_
+            (leave (G_ "invalid source 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
@@ -398,7 +451,7 @@ a checkout of the Git repository at the given URL."
   ;; key used in the option alist, and the cdr is the transformation
   ;; procedure; it is called with two arguments: the store, and a list of
   ;; things to build.
-  `((with-source . ,transform-package-source)
+  `((with-source . ,transform-package-inputs/source)
     (with-input  . ,transform-package-inputs)
     (with-graft  . ,transform-package-inputs/graft)
     (with-branch . ,transform-package-source-branch)
diff --git a/tests/scripts-build.scm b/tests/scripts-build.scm
index 32876e956a..40d7d03637 100644
--- a/tests/scripts-build.scm
+++ b/tests/scripts-build.scm
@@ -94,9 +94,9 @@
       (let* ((port (open-output-string))
              (new  (parameterize ((guix-warning-port port))
                      (t store p))))
-        (and (eq? new p)
-             (string-contains (get-output-string port)
-                              "had no effect"))))))
+        (and (eq? (package-version new) (package-version p))
+             (eq? (package-name new) (package-name p))
+             (eq? (package-source new) (package-source p)))))))
 
 (test-assert "options->transformation, with-source, PKG=URI"
   (let* ((p (dummy-package "foo"))
@@ -127,6 +127,25 @@
                        (add-to-store store (basename s) #t
                                      "sha256" s)))))))
 
+(test-assert "options->transformation, with-source, recursive"
+  (let* ((q (dummy-package "foo"))
+         (p (dummy-package "guix.scm"
+            (inputs `(("foo" ,q)))))
+         (s (search-path %load-path "guix.scm"))
+         (f (string-append "foo@42.0=" s))
+         (t (options->transformation `((with-source . ,f)))))
+    (with-store store
+      (let ((new (t store p)))
+        (and (not (eq? new p))
+             (match (package-inputs new)
+                    ((("foo" dep1))
+                     (and
+                       (string=? (package-name dep1) "foo")
+                       (string=? (package-version dep1) "42.0")
+                       (string=? (package-source dep1)
+                                 (add-to-store store (basename s) #t
+                                               "sha256" s))))))))))
+
 (test-assert "options->transformation, with-input"
   (let* ((p (dummy-package "guix.scm"
               (inputs `(("foo" ,(specification->package "coreutils"))
-- 
2.28.0
From 738fdb35af1449e245ce2e48c266c82f798d89af Mon Sep 17 00:00:00 2001
From: Jesse Gibbons <jgibbons2357+guix@gmail.com>
Date: Sat, 26 Sep 2020 16:29:25 -0600
Subject: [PATCH 2/2] news: Add entry for "--with-source"

* etc/news,scm: Add entry.
---
etc/news.scm | 8 ++++++++
1 file changed, 8 insertions(+)

Toggle diff (21 lines)
diff --git a/etc/news.scm b/etc/news.scm
index 1ef238ca2d..fcb195c679 100644
--- a/etc/news.scm
+++ b/etc/news.scm
@@ -13,6 +13,14 @@
 (channel-news
  (version 0)
 
+ (entry (commit "2d2f6c97ad1deeb2fc8a214d992c7894a7c5e293")
+        (title (en "@option{--with-source} now recursive"))
+        (body (en "The @option{--with-source} common option now uses the
+specified source for all matching dependencies of any packages guix is directed
+to work with. This option is useful for all package maintainers, developers,
+and, in general, all users who want guix to facilitate their rights to modify
+their software and share their changes.")))
+
  (entry (commit "a98712785e0b042a290420fd74e5a4a5da4fc68f")
         (title (en "New @command{guix git authenticate} command")
                (de "Neuer Befehl @command{guix git authenticate}")
-- 
2.28.0
J
J
Jesse Gibbons wrote on 8 Oct 2020 05:43
(name . Ludovic Courtès)(address . ludo@gnu.org)(address . 43193@debbugs.gnu.org)
fd9b37bf-3e8a-e123-4e1b-10fba5a7d86e@gmail.com
This is a friendly bump.

On 9/26/20 4:46 PM, Jesse Gibbons wrote:
Toggle quote (55 lines)
> Attached are the patches that make the --with-source option recursive,
> add documentation, add a test, adjust a test, and update the news.
>
> As expected, the changes I made are incompatible with the test
> "options->transformation, with-source, no matches". Since
> options->transformation, with-source does a recursive replacement, it
> returns a clone of the package in question. I have tried changing the
> comparison to eq?, eqv? and equal?, each returning false, so I settled
> on a (limited) comparison of the packages' attributes.
>
> On 9/13/20 6:55 AM, Ludovic Courtès wrote:
>> Hi,
>>
>> Jesse Gibbons <jgibbons2357@gmail.com> skribis:
>>
>>> On 9/11/20 9:43 AM, Ludovic Courtès wrote:
>> [...]
>>
>>>> So maybe drop the second clause for non-recursive replacement, and
>>>> drop
>>>> ‘transform-package-source’ as well.
>>> I included a fallback to transform-package-source because the
>>> following happens:
>>>
>>> $ ./pre-inst-env guix build --with-source=$(guix build --source
>>> hello) hello
>>> guix build: error: invalid source replacement specification:
>>> "/gnu/store/hbdalsf5lpf01x4dcknwx6xbn6n5km6k-hello-2.10.tar.gz"
>>>
>>> This does not fail when I fall back to the non-recursive logic.
>>>
>>> I can drop transform-package-source, but I will need to do some more
>>> hacking to figure out how the package name and version are parsed from
>>> the file name as described in the manual, and move it to the logic in
>>> transform-package-inputs/source.
>> Yes, that’d be nice.  Namely, if you do:
>>
>>    guix build hello --source=hello-1.2.3.tar.gz
>>
>> it should work just as now (from the source file name, we assume that
>> the source applies to package “hello”).
>>
>> Conversely, doing:
>>
>>    guix build hello --source=xyz-hello-1.2.3.tar.gz
>>
>> would have no effect.  It would not even emit a warning, unlike now.
>>
>>> I'm not going to have as much free time starting next week, so I might
>>> not be able to do that for a while, but I will try to get it done
>>> ASAP.
>> Sure, let’s stay in touch, I think we’re almost done!
>>
>> Thank you,
>> Ludo’.
L
L
Ludovic Courtès wrote on 22 Oct 2020 17:08
(name . Jesse Gibbons)(address . jgibbons2357@gmail.com)(address . 43193@debbugs.gnu.org)
87pn5as3hh.fsf@gnu.org
Hi Jesse,

Jesse Gibbons <jgibbons2357@gmail.com> skribis:

Toggle quote (3 lines)
> Attached are the patches that make the --with-source option recursive,
> add documentation, add a test, adjust a test, and update the news.

Great, and apologies for the delay.

Toggle quote (17 lines)
>>From 2d2f6c97ad1deeb2fc8a214d992c7894a7c5e293 Mon Sep 17 00:00:00 2001
> From: Jesse Gibbons <jgibbons2357+guix@gmail.com>
> Date: Thu, 3 Sep 2020 17:45:08 -0600
> Subject: [PATCH 1/2] guix: Make --with-source option recursive
>
> * guix/scripts/build.scm: (transform-package-inputs/source): new
> function
> (evaluate-source-replacement-specs): new function
> (%transformations): change with-source to use
> evaluate-source-replacement-specs
>
> * doc/guix.texi (Package Transformation Options): document it.
>
> * tests/scripts-build.scm: (options->transformation, with-source, no
> matches): adjust to new expectations.
> (options->transformation, with-source, recursive): new test.

[...]

Toggle quote (11 lines)
> +++ b/doc/guix.texi
> @@ -9142,8 +9142,8 @@ without having to type in the definitions of package variants
> @itemx --with-source=@var{package}=@var{source}
> @itemx --with-source=@var{package}@@@var{version}=@var{source}
> Use @var{source} as the source of @var{package}, and @var{version} as
> -its version number.
> -@var{source} must be a file name or a URL, as for @command{guix
> +its version number. This replacement is applied recursively on all
> +dependencies. @var{source} must be a file name or a URL, as for @command{guix
> download} (@pxref{Invoking guix download}).

Maybe s/all dependencies/all matching dependencies/?

Toggle quote (12 lines)
> +++ b/guix/scripts/build.scm
> @@ -201,9 +201,9 @@ matching URIs given in SOURCES."
> (#f
> ;; Determine the package name and version from URI.
> (call-with-values
> - (lambda ()
> - (hyphen-package-name->name+version
> - (tarball-base-name (basename uri))))
> + (lambda ()
> + (hyphen-package-name->name+version
> + (tarball-base-name (basename uri))))

Please avoid unrelated whitespace changes like this one.

Toggle quote (2 lines)
> +(define (transform-package-inputs/source replacement-specs)

Maybe call it ‘transform-package-source’ and remove the previous
‘transform-package-source’ procedure.

Toggle quote (13 lines)
> + "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=/path/to/source\" or
> +\"guile=https://www.example.com/guile-source.tar.gz\" meaning that, any
> +dependency on a package called \"guile\" must be replaced with a dependency on a
> +\"guile\" built with the source at the specified location. SPECS may also
> +simply be a file location, in which case the package name and version are parsed
> +from the file name."
> + (lambda (store obj)
> + (let* ((replacements (evaluate-source-replacement-specs replacement-specs
> + (lambda* (old file #:optional version)
> + (package-with-source store old file version))))

Please indent like the rest of the code (if you use Emacs, you can hit
M-q to have it indent the surrounding expression correctly). Here the
second line should be aligned with the first ‘a’ of ‘lambda*’.

Also please arrange to keep lines below 80 chars.

Toggle quote (4 lines)
> + (rewrite (package-input-rewriting/spec replacements))
> + (rewrite* (lambda (obj)
> + (rewrite obj))))

You can remove ‘rewrite*’ and use ‘rewrite’ directly.

Toggle quote (18 lines)
> +(define (evaluate-source-replacement-specs specs proc)
> + "Parse SPECS, a list of strings like \"guile=/path/to/source\", and return a
> +list of package pairs, where (PROC PACKAGE URL) 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* (replacement file #:optional version)
> + (lambda (old)
> + (proc old file version)))
> + (map (lambda (spec)
> + (match (string-tokenize spec %not-equal)
> + ((package-spec file)
> + (let* ((spec-list (call-with-values
> + (lambda ()
> + (package-specification->name+version+output package-spec))
> + list))
> + (name (list-ref spec-list 0))
> + (version (list-ref spec-list 1)))

Use ‘let-values’ instead:

(let-values (((name version)
(package-specification->name+version+output spec)))
…)

Also maybe s/package-spec/spec/; it’s clear enough in this context.

Toggle quote (13 lines)
> + (cons name (replacement file version))))
> + ((file)
> + (let* ((package-spec
> + (call-with-values
> + (lambda ()
> + (hyphen-package-name->name+version
> + (tarball-base-name (basename file))))
> + (lambda (name version)
> + (cons name version))))
> + (name (car package-spec))
> + (version (cdr package-spec)))
> + (cons name (replacement file version))))

‘let-values’ also.

Toggle quote (12 lines)
> +++ b/tests/scripts-build.scm
> @@ -94,9 +94,9 @@
> (let* ((port (open-output-string))
> (new (parameterize ((guix-warning-port port))
> (t store p))))
> - (and (eq? new p)
> - (string-contains (get-output-string port)
> - "had no effect"))))))
> + (and (eq? (package-version new) (package-version p))
> + (eq? (package-name new) (package-name p))
> + (eq? (package-source new) (package-source p)))))))

We can probably remove this test since the behavior it was checking no
longer exists.

Toggle quote (19 lines)
> +(test-assert "options->transformation, with-source, recursive"
> + (let* ((q (dummy-package "foo"))
> + (p (dummy-package "guix.scm"
> + (inputs `(("foo" ,q)))))
> + (s (search-path %load-path "guix.scm"))
> + (f (string-append "foo@42.0=" s))
> + (t (options->transformation `((with-source . ,f)))))
> + (with-store store
> + (let ((new (t store p)))
> + (and (not (eq? new p))
> + (match (package-inputs new)
> + ((("foo" dep1))
> + (and
> + (string=? (package-name dep1) "foo")
> + (string=? (package-version dep1) "42.0")
> + (string=? (package-source dep1)
> + (add-to-store store (basename s) #t
> + "sha256" s))))))))))

Please indent correctly.

Toggle quote (7 lines)
>>From 738fdb35af1449e245ce2e48c266c82f798d89af Mon Sep 17 00:00:00 2001
> From: Jesse Gibbons <jgibbons2357+guix@gmail.com>
> Date: Sat, 26 Sep 2020 16:29:25 -0600
> Subject: [PATCH 2/2] news: Add entry for "--with-source"
>
> * etc/news,scm: Add entry.

[...]

Toggle quote (2 lines)
> + (entry (commit "2d2f6c97ad1deeb2fc8a214d992c7894a7c5e293")
> + (title (en "@option{--with-source} now recursive"))
^
+ “package transformation option is”

Toggle quote (6 lines)
> + (body (en "The @option{--with-source} common option now uses the
> +specified source for all matching dependencies of any packages guix is directed
> +to work with. This option is useful for all package maintainers, developers,
> +and, in general, all users who want guix to facilitate their rights to modify
> +their software and share their changes.")))

Usually there’s an extra sentence like “Run info …” explaining how to
read the relevant part of the manual; it may be a good idea to add it.

Could you send an updated patch? Hopefully the last one!

Thanks,
Ludo’.
?