[PATCH] import: hackage: Accept local source for package.

OpenSubmitted by Xinglu Chen.
Details
3 participants
  • Ludovic Courtès
  • Xinglu Chen
  • zimoun
Owner
unassigned
Severity
normal
X
X
Xinglu Chen wrote on 13 Jun 2021 11:46
(address . guix-patches@gnu.org)
a7ff1db35e4294c161b871d47a8908af12d1efd3.1623577110.git.public@yoctocell.xyz
When developing a Haskell package it is often useful to have a Guix package
definition for that package, previously one would have to write that package
definition by hand, and if the .cabal file changed one would manually update
the Guix package definition.

This commit allows one to specify a custom source for their package, meaning
that one could programatically generate a Guix package definition for their
local Haskell package. If the .cabal file changes, the generated package
definition will also change accordingly. One could for instance write the
following in a guix.scm file:

(define-values (ghc-haskeme deps)
(call-with-input-file "haskeme.cabal"
(lambda (port)
(hackage->guix-package
"haskeme"
#:port port
#:source (local-file "." "haskeme-checkout"
#:recursive? #t
#:select? hg-predicate)))))

ghc-haskeme

Invoking ‘guix build -f guix.scm’ would then always build an up-to-date
version of the package.

* guix/import/hackage.scm (hackage-module->sexp): Add optional keyword
argument ‘source’
(hackage->guix-package): Likewise.
* tests/hackage.scm (eval-test-with-cabal): Likewise.
("hackage->guix-package local source"): New test.
---
Without this I would have to manually write my Guix package definition,
and manually update the ‘inputs’ field if I added a new dependency in my
.cabal file. This patch offers something similar to pkgs.callCabal2nix
(I could find any link to the docs, classic Nix) in Nixpkgs where i can
just write the following

Toggle snippet (12 lines)
let
haskellPackages = pkgs.haskell.packages.${compiler}.override {
overrides = hpNew: hpOld: {
haskeme = hpNew.callCabal2nix "haskeme" ./. { };
};
};
in
{
haskeme = haskellPackages.haskeme;
}

to get a Nix package definition of my Haskell package.

guix/import/hackage.scm | 43 ++++++++++++++++++++++++++---------------
tests/hackage.scm | 28 +++++++++++++++++++++++++--
2 files changed, 53 insertions(+), 18 deletions(-)

Toggle diff (140 lines)
diff --git a/guix/import/hackage.scm b/guix/import/hackage.scm
index f94a1e7087..326ab92365 100644
--- a/guix/import/hackage.scm
+++ b/guix/import/hackage.scm
@@ -227,10 +227,13 @@ package being processed and is used to filter references to itself."
           dependencies))
 
 (define* (hackage-module->sexp cabal cabal-hash
-                               #:key (include-test-dependencies? #t))
+                               #:key
+                               (include-test-dependencies? #t)
+                               (source #f))
   "Return the `package' S-expression for a Cabal package.  CABAL is the
-representation of a Cabal file as produced by 'read-cabal'.  CABAL-HASH is
-the hash of the Cabal file."
+representation of a Cabal file as produced by 'read-cabal'.  CABAL-HASH is the
+hash of the Cabal file.  If SOURCE is specified, it will be used as the source
+for the package."
 
   (define name
     (cabal-package-name cabal))
@@ -294,20 +297,24 @@ the hash of the Cabal file."
       (() '())
       (args `((arguments (,'quasiquote ,args))))))
 
-  (let ((tarball (with-store store
-                   (download-to-store store source-url))))
+  (let ((tarball (if source
+                     #f
+                     (with-store store
+                       (download-to-store store source-url)))))
     (values
      `(package
         (name ,(hackage-name->package-name name))
         (version ,version)
-        (source (origin
-                  (method url-fetch)
-                  (uri (string-append ,@(factorize-uri source-url version)))
-                  (sha256
-                   (base32
-                    ,(if tarball
-                         (bytevector->nix-base32-string (file-sha256 tarball))
-                         "failed to download tar archive")))))
+        (source ,(if source
+                     source
+                     `(origin
+                        (method url-fetch)
+                        (uri (string-append ,@(factorize-uri source-url version)))
+                        (sha256
+                         (base32
+                          ,(if tarball
+                               (bytevector->nix-base32-string (file-sha256 tarball))
+                               "failed to download tar archive"))))))
         (build-system haskell-build-system)
         ,@(maybe-inputs 'inputs dependencies)
         ,@(maybe-inputs 'native-inputs native-dependencies)
@@ -321,10 +328,12 @@ the hash of the Cabal file."
 (define* (hackage->guix-package package-name #:key
                                 (include-test-dependencies? #t)
                                 (port #f)
+                                (source #f)
                                 (cabal-environment '()))
   "Fetch the Cabal file for PACKAGE-NAME from hackage.haskell.org, or, if the
-called with keyword parameter PORT, from PORT.  Return the `package'
-S-expression corresponding to that package, or #f on failure.
+called with keyword parameter PORT, from PORT.  If SOURCE is specified, use it
+as the source for the package instead of trying to fetch a tarball.  Return
+the `package' S-expression corresponding to that package, or #f on failure.
 CABAL-ENVIRONMENT is an alist defining the environment in which the Cabal
 conditionals are evaluated.  The accepted keys are: \"os\", \"arch\", \"impl\"
 and the name of a flag.  The value associated with a flag has to be either the
@@ -338,7 +347,9 @@ respectively."
                     (hackage-fetch-and-hash package-name))))
     (and=> cabal-meta (compose (cut hackage-module->sexp <> cabal-hash
                                     #:include-test-dependencies?
-                                    include-test-dependencies?)
+                                    include-test-dependencies?
+                                    #:source
+                                    source)
                                (cut eval-cabal <> cabal-environment)))))
 
 (define hackage->guix-package/m                   ;memoized variant
diff --git a/tests/hackage.scm b/tests/hackage.scm
index 66a13d9881..54590dcece 100644
--- a/tests/hackage.scm
+++ b/tests/hackage.scm
@@ -22,6 +22,7 @@
   #:use-module (guix import cabal)
   #:use-module (guix import hackage)
   #:use-module (guix tests)
+  #:use-module (guix gexp)
   #:use-module (srfi srfi-64)
   #:use-module (ice-9 match))
 
@@ -186,9 +187,28 @@ library
     ('description (? string?))
     ('license 'license:bsd-3)))
 
-(define* (eval-test-with-cabal test-cabal matcher #:key (cabal-environment '()))
+(define-package-matcher match-ghc-foo-local-source
+  ('package
+    ('name "ghc-foo")
+    ('version "1.0.0")
+    ('source
+     (? file-like?))
+    ('build-system 'haskell-build-system)
+    ('inputs
+     ('quasiquote
+      (("ghc-http" ('unquote 'ghc-http)))))
+    ('home-page "http://test.org")
+    ('synopsis (? string?))
+    ('description (? string?))
+    ('license 'license:bsd-3)))
+
+(define* (eval-test-with-cabal test-cabal matcher
+                               #:key (cabal-environment '()) (source #f))
   (define port (open-input-string test-cabal))
-  (matcher (hackage->guix-package "foo" #:port port #:cabal-environment cabal-environment)))
+  (matcher (hackage->guix-package "foo"
+                                  #:port port
+                                  #:cabal-environment cabal-environment
+                                  #:source source)))
 
 (test-assert "hackage->guix-package test 1"
   (eval-test-with-cabal test-cabal-1 match-ghc-foo))
@@ -208,6 +228,10 @@ library
   (eval-test-with-cabal test-cabal-5 match-ghc-foo
                         #:cabal-environment '(("impl" . "ghc-7.8"))))
 
+(test-assert "hackage->guix-package local source"
+  (eval-test-with-cabal test-cabal-1 match-ghc-foo-local-source
+                        #:source (plain-file "dummy source" "source")))
+
 (define-package-matcher match-ghc-foo-6
   ('package
     ('name "ghc-foo")

base-commit: acb858881901aa28499f83f40d3e04d6e4749453
-- 
2.32.0
L
L
Ludovic Courtès wrote on 29 Jun 2021 11:44
(name . Xinglu Chen)(address . public@yoctocell.xyz)(address . 48999@debbugs.gnu.org)
87wnqdt37b.fsf@gnu.org
Hi,

Xinglu Chen <public@yoctocell.xyz> skribis:

Toggle quote (32 lines)
> When developing a Haskell package it is often useful to have a Guix package
> definition for that package, previously one would have to write that package
> definition by hand, and if the .cabal file changed one would manually update
> the Guix package definition.
>
> This commit allows one to specify a custom source for their package, meaning
> that one could programatically generate a Guix package definition for their
> local Haskell package. If the .cabal file changes, the generated package
> definition will also change accordingly. One could for instance write the
> following in a guix.scm file:
>
> (define-values (ghc-haskeme deps)
> (call-with-input-file "haskeme.cabal"
> (lambda (port)
> (hackage->guix-package
> "haskeme"
> #:port port
> #:source (local-file "." "haskeme-checkout"
> #:recursive? #t
> #:select? hg-predicate)))))
>
> ghc-haskeme
>
> Invoking ‘guix build -f guix.scm’ would then always build an up-to-date
> version of the package.
>
> * guix/import/hackage.scm (hackage-module->sexp): Add optional keyword
> argument ‘source’
> (hackage->guix-package): Likewise.
> * tests/hackage.scm (eval-test-with-cabal): Likewise.
> ("hackage->guix-package local source"): New test.

Looks like a nice improvement.

What I don’t get is that this functionality doesn’t seem to be available
from the CLI, which the patch doesn’t change. Or am I missing
something?

Thanks,
Ludo’.
X
X
Xinglu Chen wrote on 29 Jun 2021 21:00
Re: [bug#48999] [PATCH] import: hackage: Accept local source for package.
(name . Ludovic Courtès)(address . ludo@gnu.org)(address . 48999@debbugs.gnu.org)
874kdgbio8.fsf@yoctocell.xyz
On Tue, Jun 29 2021, Ludovic Courtès wrote:

Toggle quote (42 lines)
> Hi,
>
> Xinglu Chen <public@yoctocell.xyz> skribis:
>
>> When developing a Haskell package it is often useful to have a Guix package
>> definition for that package, previously one would have to write that package
>> definition by hand, and if the .cabal file changed one would manually update
>> the Guix package definition.
>>
>> This commit allows one to specify a custom source for their package, meaning
>> that one could programatically generate a Guix package definition for their
>> local Haskell package. If the .cabal file changes, the generated package
>> definition will also change accordingly. One could for instance write the
>> following in a guix.scm file:
>>
>> (define-values (ghc-haskeme deps)
>> (call-with-input-file "haskeme.cabal"
>> (lambda (port)
>> (hackage->guix-package
>> "haskeme"
>> #:port port
>> #:source (local-file "." "haskeme-checkout"
>> #:recursive? #t
>> #:select? hg-predicate)))))
>>
>> ghc-haskeme
>>
>> Invoking ‘guix build -f guix.scm’ would then always build an up-to-date
>> version of the package.
>>
>> * guix/import/hackage.scm (hackage-module->sexp): Add optional keyword
>> argument ‘source’
>> (hackage->guix-package): Likewise.
>> * tests/hackage.scm (eval-test-with-cabal): Likewise.
>> ("hackage->guix-package local source"): New test.
>
> Looks like a nice improvement.
>
> What I don’t get is that this functionality doesn’t seem to be available
> from the CLI, which the patch doesn’t change. Or am I missing
> something?

No, I don’t think this functionality is available from the CLI since
‘hackage->guix-package’ is not called with the #:source keyword
argument. Once all the other importers (or those where it makes sense
to do this) get this functionality, it would be a good idea to add an
option for reading a .cabal/setup.py/whatever file and generating a
package definition from that.
-----BEGIN PGP SIGNATURE-----

iQJJBAEBCAAzFiEEAVhh4yyK5+SEykIzrPUJmaL7XHkFAmDbbbcVHHB1YmxpY0B5
b2N0b2NlbGwueHl6AAoJEKz1CZmi+1x5ht4P/Rw4PHbyvzzc8DTqpSjo1KuRyYah
u9TTtjED/QqWpZ+eIKtfgdAyCvFDGRDLcWcjaXG+l5i9+BLxXmQpeF5zFb+z9a5i
/1EUlpz8i/vY4flX0uo/iz4xkmAtjoJo6sPZwWmEvlItHAMpCPe/5e7mlnzOw1wf
DDBJP6DvMJSFtBGmdtW7HFYYMVHaVqw6xX3hUTkOTOc7XmvXEVPjYLPyB6r4fmH9
Wl62Eyhnu4ARYbNBVrrz9Ot7Zq1hwFQl5oqljti05TmA/Lhlz9HtN5ipNt0f5qCm
Uy29UnvIwGFHPiEaF/rYhVEoZreXfFh9s1KrONoQOeF0aksEPakJk4b/qHbUVLWx
GbOgrFUqAfRiqmZG1x2RYpe+O1EOEDe0ukeNJE9njBJv6svN4GvvJ3hHMOp3+7Ck
jOv0w+FZ7MNqxd40dSiDTEbu2Oaj36XYG0gdIiF5dQvdrcUGes2sd8uC7ciMFg9E
BvzWhMndiiTkn13ndFl2D6BvAdqDNHnZKPJ+ZVS2g7XSAH3gS6js0id0O4ku+dYY
al5p2lLzjDaJGNrcrD17FVXPpDzKTzYQfi/6smWYL1uw6mTZT5aLokDdQ1Pydh8I
OZ4s4+8MCQ9vWGAgfNe78IZuwwzdkMiAB7ZAKgb9yoyy99lb5nPQ0H20hubOfzRZ
+BvRci5vmFZN5nm8
=QQ7p
-----END PGP SIGNATURE-----

L
L
Ludovic Courtès wrote on 30 Jun 2021 11:17
(name . Xinglu Chen)(address . public@yoctocell.xyz)(address . 48999@debbugs.gnu.org)
877dibpv8o.fsf@gnu.org
Hi,

Xinglu Chen <public@yoctocell.xyz> skribis:

Toggle quote (48 lines)
> On Tue, Jun 29 2021, Ludovic Courtès wrote:
>
>> Hi,
>>
>> Xinglu Chen <public@yoctocell.xyz> skribis:
>>
>>> When developing a Haskell package it is often useful to have a Guix package
>>> definition for that package, previously one would have to write that package
>>> definition by hand, and if the .cabal file changed one would manually update
>>> the Guix package definition.
>>>
>>> This commit allows one to specify a custom source for their package, meaning
>>> that one could programatically generate a Guix package definition for their
>>> local Haskell package. If the .cabal file changes, the generated package
>>> definition will also change accordingly. One could for instance write the
>>> following in a guix.scm file:
>>>
>>> (define-values (ghc-haskeme deps)
>>> (call-with-input-file "haskeme.cabal"
>>> (lambda (port)
>>> (hackage->guix-package
>>> "haskeme"
>>> #:port port
>>> #:source (local-file "." "haskeme-checkout"
>>> #:recursive? #t
>>> #:select? hg-predicate)))))
>>>
>>> ghc-haskeme
>>>
>>> Invoking ‘guix build -f guix.scm’ would then always build an up-to-date
>>> version of the package.
>>>
>>> * guix/import/hackage.scm (hackage-module->sexp): Add optional keyword
>>> argument ‘source’
>>> (hackage->guix-package): Likewise.
>>> * tests/hackage.scm (eval-test-with-cabal): Likewise.
>>> ("hackage->guix-package local source"): New test.
>>
>> Looks like a nice improvement.
>>
>> What I don’t get is that this functionality doesn’t seem to be available
>> from the CLI, which the patch doesn’t change. Or am I missing
>> something?
>
> No, I don’t think this functionality is available from the CLI since
> ‘hackage->guix-package’ is not called with the #:source keyword
> argument.

IOW, this functionality is not accessible, unless you use the Scheme API
as in the example above, right?

Toggle quote (5 lines)
> Once all the other importers (or those where it makes sense to do
> this) get this functionality, it would be a good idea to add an option
> for reading a .cabal/setup.py/whatever file and generating a package
> definition from that.

‘guix import hackage’ could support it even if other importers don’t
have equivalent functionality, no?

Thanks,
Ludo’.
Z
Z
zimoun wrote on 30 Jun 2021 16:10
(address . 48999@debbugs.gnu.org)
86pmw3789g.fsf@gmail.com
Hi,

On Wed, 30 Jun 2021 at 11:17, Ludovic Courtès <ludo@gnu.org> wrote:
Toggle quote (17 lines)
>>> Xinglu Chen <public@yoctocell.xyz> skribis:

>>>> (define-values (ghc-haskeme deps)
>>>> (call-with-input-file "haskeme.cabal"
>>>> (lambda (port)
>>>> (hackage->guix-package
>>>> "haskeme"
>>>> #:port port
>>>> #:source (local-file "." "haskeme-checkout"
>>>> #:recursive? #t
>>>> #:select? hg-predicate)))))
>>>>
>>>> ghc-haskeme
>>>>
>>>> Invoking ‘guix build -f guix.scm’ would then always build an up-to-date
>>>> version of the package.

[...]

Toggle quote (19 lines)
>>> What I don’t get is that this functionality doesn’t seem to be available
>>> from the CLI, which the patch doesn’t change. Or am I missing
>>> something?
>>
>> No, I don’t think this functionality is available from the CLI since
>> ‘hackage->guix-package’ is not called with the #:source keyword
>> argument.
>
> IOW, this functionality is not accessible, unless you use the Scheme API
> as in the example above, right?
>
>> Once all the other importers (or those where it makes sense to do
>> this) get this functionality, it would be a good idea to add an option
>> for reading a .cabal/setup.py/whatever file and generating a package
>> definition from that.
>
> ‘guix import hackage’ could support it even if other importers don’t
> have equivalent functionality, no?

From my understanding, there are 2 levels:

1. simplify the Scheme snippet for developing local “foreign” package,
i.e., “guix build -f guix.scm” with a simpler ’guix.scm’ file.

2. an option to import local package,
e.g., “guix import hackage --path=.”

and this for (almost) all the importers.


Cheers,
simon
X
X
Xinglu Chen wrote on 4 Jul 2021 12:43
(name . Ludovic Courtès)(address . ludo@gnu.org)(address . 48999@debbugs.gnu.org)
87h7hajr5s.fsf@yoctocell.xyz
On Wed, Jun 30 2021, Ludovic Courtès wrote:

Toggle quote (55 lines)
> Hi,
>
> Xinglu Chen <public@yoctocell.xyz> skribis:
>
>> On Tue, Jun 29 2021, Ludovic Courtès wrote:
>>
>>> Hi,
>>>
>>> Xinglu Chen <public@yoctocell.xyz> skribis:
>>>
>>>> When developing a Haskell package it is often useful to have a Guix package
>>>> definition for that package, previously one would have to write that package
>>>> definition by hand, and if the .cabal file changed one would manually update
>>>> the Guix package definition.
>>>>
>>>> This commit allows one to specify a custom source for their package, meaning
>>>> that one could programatically generate a Guix package definition for their
>>>> local Haskell package. If the .cabal file changes, the generated package
>>>> definition will also change accordingly. One could for instance write the
>>>> following in a guix.scm file:
>>>>
>>>> (define-values (ghc-haskeme deps)
>>>> (call-with-input-file "haskeme.cabal"
>>>> (lambda (port)
>>>> (hackage->guix-package
>>>> "haskeme"
>>>> #:port port
>>>> #:source (local-file "." "haskeme-checkout"
>>>> #:recursive? #t
>>>> #:select? hg-predicate)))))
>>>>
>>>> ghc-haskeme
>>>>
>>>> Invoking ‘guix build -f guix.scm’ would then always build an up-to-date
>>>> version of the package.
>>>>
>>>> * guix/import/hackage.scm (hackage-module->sexp): Add optional keyword
>>>> argument ‘source’
>>>> (hackage->guix-package): Likewise.
>>>> * tests/hackage.scm (eval-test-with-cabal): Likewise.
>>>> ("hackage->guix-package local source"): New test.
>>>
>>> Looks like a nice improvement.
>>>
>>> What I don’t get is that this functionality doesn’t seem to be available
>>> from the CLI, which the patch doesn’t change. Or am I missing
>>> something?
>>
>> No, I don’t think this functionality is available from the CLI since
>> ‘hackage->guix-package’ is not called with the #:source keyword
>> argument.
>
> IOW, this functionality is not accessible, unless you use the Scheme API
> as in the example above, right?

Yes.

Toggle quote (8 lines)
>> Once all the other importers (or those where it makes sense to do
>> this) get this functionality, it would be a good idea to add an option
>> for reading a .cabal/setup.py/whatever file and generating a package
>> definition from that.
>
> ‘guix import hackage’ could support it even if other importers don’t
> have equivalent functionality, no?

Sure, that could work too.
-----BEGIN PGP SIGNATURE-----

iQJJBAEBCAAzFiEEAVhh4yyK5+SEykIzrPUJmaL7XHkFAmDhkL8VHHB1YmxpY0B5
b2N0b2NlbGwueHl6AAoJEKz1CZmi+1x5v9gP/3ILbHXZ8Dr9zpUJfDufEUsCfQNF
Ws2UNRvmE1AFvclQTOjnvZih2UcLUa/3IRlUryuGkAUAEMExapUx70UjZUhx3VWI
LUZ52xvmnlCo1IbKOLmyTtY3fMEyUQChDw8CojUywj4xJOpW2VIIWEu4Vs4Q3IWs
OQY5X4rByuVgQDxpzD31Rnf6uXmNPjSLa6Dudm/6g3PFffy6f7JahaRx5QDpBsOh
I+vv1ejii1kEu8RAacg1y51i1CDq05/FmNAYzkXudfjqFOuK5XEwfYT/n+OuKtpH
r3LDiycVjbxUuWiLGX/nnJxt7APAnuyrgCKonVONpiimpPgThsTdEs0MVIV+UHnY
Bq4nV3STIsRPjPV/sa9vGbYPsX2ahwJunLMvrX9HV+REYtoDYYCnoGg6GdcHghV9
gcXppPNZtRun7FTG9ffA5a6K189fpwOHPykKBytvm4Vn35JBriBmB6EwoRsN5wyR
B72q7MXRDfWh422HSWmhSzQKw4JLMTimegFnoQLopKI68zTqxoKI0lA9KeXPtm/x
vjPugFRAVJnW7PX0ZhZn0NF52+PNjBnziSFh7M/46/hriHjDbm2U6jFdd1LmjHit
m1/1yXIAdEtwaE+KDHwh8XR3G4MGXk6go6qUnpdJFa7TtbICCsdDTzFyHX6hT6R6
6LHJ1xJw8ROAsX8G
=44ix
-----END PGP SIGNATURE-----

X
X
Xinglu Chen wrote on 4 Jul 2021 13:53
[PATCH v2 0/3] Import Haskell packages from the local filesystem
(address . 48999@debbugs.gnu.org)
cover.1625399149.git.public@yoctocell.xyz
Changes since v1:

* Add ‘--path’ command line option for importing the package from the
local filesystem.

* Add ‘git-repository?’ and ‘hg-repository?’ procedures for correctly
setting the #:select? keyword (‘git-predicate’ or ‘hg-predicate’) for
‘local-file’. Other VCS don’t have a ‘-predicate’ procedure, so I
didn’t bother adding those.

Patch [1/3] hasn’t changed since v1.

Xinglu Chen (3):
import: hackage: Accept local source for package.
import: utils: Add predicates for checking VCS repositories.
scripts: import: hackage: Add option to import package from local
filesystem.

guix/import/hackage.scm | 43 +++++++++++++++++++++------------
guix/import/utils.scm | 15 ++++++++++++
guix/scripts/import/hackage.scm | 43 +++++++++++++++++++++++++++------
tests/hackage.scm | 28 +++++++++++++++++++--
4 files changed, 103 insertions(+), 26 deletions(-)


base-commit: b65af6ed9120234cf655e8e76317558cfbd02477
--
2.32.0
-----BEGIN PGP SIGNATURE-----

iQJJBAEBCAAzFiEEAVhh4yyK5+SEykIzrPUJmaL7XHkFAmDhoVIVHHB1YmxpY0B5
b2N0b2NlbGwueHl6AAoJEKz1CZmi+1x5KgkQALA5ub5ARbFCFAuH6UTSRzI4ar+c
t+v1H2OtFLh+O4JzpnPjHvJ9wXh2Kus88IBmfQ0O4kHibVW3IDleQXnXoXBlm2tK
UoZEEZlfx2c+0vRzF+7YAYPZslOhwRoAIZJhDsL9P9kkYx6YsXJVNypUqK3ALo5S
LAIKLAvWGRjbQKRaGg96auQp6q9awDfDCBRYgGY1MPuHi00mygpo8LgBJDH+xyQA
7J5FRcHPhoA1LbDtod5WEoqixkhbL1Wp9upkeQHVdFPiMH5g45a3PSYTepKP6ELc
foA3Bo6ipuL6tFUYN+ITaBj0deV5aNY5KcnvCqj//0bcle2+1qBQwhb9nC2gvNdL
BIM3EHJEDJRnSTeA5S+hMTb1MfjoZVXH+ej0US1rSRh4KcInpZkeg3vH3cRMkeyw
8ZP8FEr5PMX4puEUJ5nmyXqbqxLjvMlZcmIFQFPNCHtH6KfUK4HurY+AHi6BKWI5
PqR2ef6lsxRaKBZFWHipS/vg3CDWRHq99sBaQIeVztKudVvReSBrWlfypCtmVLqU
aOZ2+KqlusThNE4yuXaT18RSUN1kFYyZzb9NTrsOsbRgKzJbr+nA+KePb/H1gpbc
rtswGH3EcDMbxaty2c/fMI89Ei8ChrXCy+MWN9ok15KOE/QQFF3MiJKmmapyv31V
EMGFdDfjufIkYzeY
=m9X+
-----END PGP SIGNATURE-----

X
X
Xinglu Chen wrote on 4 Jul 2021 13:54
[PATCH v2 1/3] import: hackage: Accept local source for package.
(address . 48999@debbugs.gnu.org)
e3a7d1d0538b6bbfb525c93aaeba9f53474f4c3a.1625399149.git.public@yoctocell.xyz
When developing a Haskell package it is often useful to have a Guix package
definition for that package, previously one would have to write that package
definition by hand, and if the .cabal file changed one would manually update
the Guix package definition.

This commit allows one to specify a custom source for their package, meaning
that one could programatically generate a Guix package definition for their
local Haskell package. If the .cabal file changes, the generated package
definition will also change accordingly. One could for instance write the
following in a guix.scm file:

(define-values (ghc-haskeme deps)
(call-with-input-file "haskeme.cabal"
(lambda (port)
(hackage->guix-package
"haskeme"
#:port port
#:source (local-file "." "haskeme-checkout"
#:recursive? #t
#:select? hg-predicate)))))

ghc-haskeme

Invoking ‘guix build -f guix.scm’ would then always build an up-to-date
version of the package.

* guix/import/hackage.scm (hackage-module->sexp): Add optional keyword
argument ‘source’
(hackage->guix-package): Likewise.
* tests/hackage.scm (eval-test-with-cabal): Likewise.
("hackage->guix-package local source"): New test.
---
guix/import/hackage.scm | 43 ++++++++++++++++++++++++++---------------
tests/hackage.scm | 28 +++++++++++++++++++++++++--
2 files changed, 53 insertions(+), 18 deletions(-)

Toggle diff (138 lines)
diff --git a/guix/import/hackage.scm b/guix/import/hackage.scm
index f94a1e7087..326ab92365 100644
--- a/guix/import/hackage.scm
+++ b/guix/import/hackage.scm
@@ -227,10 +227,13 @@ package being processed and is used to filter references to itself."
           dependencies))
 
 (define* (hackage-module->sexp cabal cabal-hash
-                               #:key (include-test-dependencies? #t))
+                               #:key
+                               (include-test-dependencies? #t)
+                               (source #f))
   "Return the `package' S-expression for a Cabal package.  CABAL is the
-representation of a Cabal file as produced by 'read-cabal'.  CABAL-HASH is
-the hash of the Cabal file."
+representation of a Cabal file as produced by 'read-cabal'.  CABAL-HASH is the
+hash of the Cabal file.  If SOURCE is specified, it will be used as the source
+for the package."
 
   (define name
     (cabal-package-name cabal))
@@ -294,20 +297,24 @@ the hash of the Cabal file."
       (() '())
       (args `((arguments (,'quasiquote ,args))))))
 
-  (let ((tarball (with-store store
-                   (download-to-store store source-url))))
+  (let ((tarball (if source
+                     #f
+                     (with-store store
+                       (download-to-store store source-url)))))
     (values
      `(package
         (name ,(hackage-name->package-name name))
         (version ,version)
-        (source (origin
-                  (method url-fetch)
-                  (uri (string-append ,@(factorize-uri source-url version)))
-                  (sha256
-                   (base32
-                    ,(if tarball
-                         (bytevector->nix-base32-string (file-sha256 tarball))
-                         "failed to download tar archive")))))
+        (source ,(if source
+                     source
+                     `(origin
+                        (method url-fetch)
+                        (uri (string-append ,@(factorize-uri source-url version)))
+                        (sha256
+                         (base32
+                          ,(if tarball
+                               (bytevector->nix-base32-string (file-sha256 tarball))
+                               "failed to download tar archive"))))))
         (build-system haskell-build-system)
         ,@(maybe-inputs 'inputs dependencies)
         ,@(maybe-inputs 'native-inputs native-dependencies)
@@ -321,10 +328,12 @@ the hash of the Cabal file."
 (define* (hackage->guix-package package-name #:key
                                 (include-test-dependencies? #t)
                                 (port #f)
+                                (source #f)
                                 (cabal-environment '()))
   "Fetch the Cabal file for PACKAGE-NAME from hackage.haskell.org, or, if the
-called with keyword parameter PORT, from PORT.  Return the `package'
-S-expression corresponding to that package, or #f on failure.
+called with keyword parameter PORT, from PORT.  If SOURCE is specified, use it
+as the source for the package instead of trying to fetch a tarball.  Return
+the `package' S-expression corresponding to that package, or #f on failure.
 CABAL-ENVIRONMENT is an alist defining the environment in which the Cabal
 conditionals are evaluated.  The accepted keys are: \"os\", \"arch\", \"impl\"
 and the name of a flag.  The value associated with a flag has to be either the
@@ -338,7 +347,9 @@ respectively."
                     (hackage-fetch-and-hash package-name))))
     (and=> cabal-meta (compose (cut hackage-module->sexp <> cabal-hash
                                     #:include-test-dependencies?
-                                    include-test-dependencies?)
+                                    include-test-dependencies?
+                                    #:source
+                                    source)
                                (cut eval-cabal <> cabal-environment)))))
 
 (define hackage->guix-package/m                   ;memoized variant
diff --git a/tests/hackage.scm b/tests/hackage.scm
index 53972fc643..3083a5d4df 100644
--- a/tests/hackage.scm
+++ b/tests/hackage.scm
@@ -22,6 +22,7 @@
   #:use-module (guix import cabal)
   #:use-module (guix import hackage)
   #:use-module (guix tests)
+  #:use-module (guix gexp)
   #:use-module (srfi srfi-64)
   #:use-module (ice-9 match))
 
@@ -186,9 +187,28 @@ library
     ('description (? string?))
     ('license 'license:bsd-3)))
 
-(define* (eval-test-with-cabal test-cabal matcher #:key (cabal-environment '()))
+(define-package-matcher match-ghc-foo-local-source
+  ('package
+    ('name "ghc-foo")
+    ('version "1.0.0")
+    ('source
+     (? file-like?))
+    ('build-system 'haskell-build-system)
+    ('inputs
+     ('quasiquote
+      (("ghc-http" ('unquote 'ghc-http)))))
+    ('home-page "http://test.org")
+    ('synopsis (? string?))
+    ('description (? string?))
+    ('license 'license:bsd-3)))
+
+(define* (eval-test-with-cabal test-cabal matcher
+                               #:key (cabal-environment '()) (source #f))
   (define port (open-input-string test-cabal))
-  (matcher (hackage->guix-package "foo" #:port port #:cabal-environment cabal-environment)))
+  (matcher (hackage->guix-package "foo"
+                                  #:port port
+                                  #:cabal-environment cabal-environment
+                                  #:source source)))
 
 (test-assert "hackage->guix-package test 1"
   (eval-test-with-cabal test-cabal-1 match-ghc-foo))
@@ -208,6 +228,10 @@ library
   (eval-test-with-cabal test-cabal-5 match-ghc-foo
                         #:cabal-environment '(("impl" . "ghc-7.8"))))
 
+(test-assert "hackage->guix-package local source"
+  (eval-test-with-cabal test-cabal-1 match-ghc-foo-local-source
+                        #:source (plain-file "dummy source" "source")))
+
 (define-package-matcher match-ghc-foo-6
   ('package
     ('name "ghc-foo")
-- 
2.32.0
X
X
Xinglu Chen wrote on 4 Jul 2021 13:54
[PATCH v2 2/3] import: utils: Add predicates for checking VCS repositories.
(address . 48999@debbugs.gnu.org)
6f3fa1769c57d6c81765939a40b1c505d0cefb66.1625399149.git.public@yoctocell.xyz
* guix/import/utils.scm (git-repository?, hg-repository?): New procedures.
---
guix/import/utils.scm | 15 +++++++++++++++
1 file changed, 15 insertions(+)

Toggle diff (49 lines)
diff --git a/guix/import/utils.scm b/guix/import/utils.scm
index d817318a91..bcf26ae363 100644
--- a/guix/import/utils.scm
+++ b/guix/import/utils.scm
@@ -8,6 +8,7 @@
 ;;; Copyright © 2020 Helio Machado <0x2b3bfa0+guix@googlemail.com>
 ;;; Copyright © 2020 Martin Becze <mjbecze@riseup.net>
 ;;; Copyright © 2021 Maxim Cournoyer <maxim.cournoyer@gmail.com>
+;;; Copyright © 2021 Xinglu Chen <public@yoctocell.xyz>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -43,6 +44,7 @@
   #:use-module (ice-9 rdelim)
   #:use-module (ice-9 receive)
   #:use-module (ice-9 regex)
+  #:use-module (ice-9 ftw)
   #:use-module (srfi srfi-1)
   #:use-module (srfi srfi-9)
   #:use-module (srfi srfi-11)
@@ -74,6 +76,9 @@
 
             guix-name
 
+            git-repository?
+            hg-repository?
+            
             recursive-import))
 
 (define (factorize-uri uri version)
@@ -422,6 +427,16 @@ separated by PRED."
                                       (chr (char-downcase chr)))
                                     name)))
 
+(define (git-repository? directory)
+  "Check whether DIRECTORY is a Git repository."
+  (let ((contents (scandir directory)))
+    (if (member ".git" contents) #t #f)))
+
+(define (hg-repository? directory)
+  "Check whether DIRECTORY is a Hg repository."
+  (let ((contents (scandir directory)))
+    (if (member ".hg" contents) #t #f)))
+
 (define (topological-sort nodes
                           node-dependencies
                           node-name)
-- 
2.32.0
X
X
Xinglu Chen wrote on 4 Jul 2021 13:54
[PATCH v2 3/3] scripts: import: hackage: Add option to import package from local filesystem.
(address . 48999@debbugs.gnu.org)
52f526989b25468210fa05e62580589f2c1cc4ea.1625399149.git.public@yoctocell.xyz
This adds a ‘--path’ option for importing a Haskell package from the local
filesystem

* guix/scripts/import/hackage.scm (show-help, %options): Add ‘-p’ and ‘--path’
options.
(guix-import-hackage): Set the #:port and #:source keywords when the ‘--path’
option is used.
---
guix/scripts/import/hackage.scm | 43 +++++++++++++++++++++++++++------
1 file changed, 35 insertions(+), 8 deletions(-)

Toggle diff (99 lines)
diff --git a/guix/scripts/import/hackage.scm b/guix/scripts/import/hackage.scm
index 906dca24b1..8728791b52 100644
--- a/guix/scripts/import/hackage.scm
+++ b/guix/scripts/import/hackage.scm
@@ -1,6 +1,7 @@
 ;;; GNU Guix --- Functional package management for GNU
 ;;; Copyright © 2015 Federico Beffa <beffa@fbengineering.ch>
 ;;; Copyright © 2018 Ricardo Wurmus <rekado@elephly.net>
+;;; Copyright © 2021 Xinglu Chen <public@yoctocell.xyz>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -22,6 +23,7 @@
   #:use-module (guix utils)
   #:use-module (guix packages)
   #:use-module (guix scripts)
+  #:use-module (guix import utils)
   #:use-module (guix import hackage)
   #:use-module (guix scripts import)
   #:use-module (srfi srfi-1)
@@ -29,6 +31,7 @@
   #:use-module (srfi srfi-37)
   #:use-module (ice-9 match)
   #:use-module (ice-9 format)
+  #:use-module (rnrs io ports)
   #:export (guix-import-hackage))
 
 
@@ -62,6 +65,8 @@ version.\n"))
   (display (G_ "
   -s, --stdin                  read from standard input"))
   (display (G_ "
+  -p, --path=DIR               use local directory as source"))
+  (display (G_ "
   -t, --no-test-dependencies   don't include test-only dependencies"))
   (display (G_ "
   -V, --version                display version information and exit"))
@@ -87,6 +92,11 @@ version.\n"))
                    (alist-cons 'read-from-stdin? #t
                                (alist-delete 'read-from-stdin?
                                              result))))
+         (option '(#\p "path") #t #f
+                 (lambda (opt name arg result)
+                   (alist-cons 'read-path arg
+                                (alist-delete 'read-path
+                                              result))))
          (option '(#\e "cabal-environment") #t #f
                  (lambda (opt name arg result)
                    (alist-cons 'cabal-environment (read/eval arg)
@@ -113,22 +123,39 @@ version.\n"))
                 %default-options))
 
   (define (run-importer package-name opts error-fn)
-    (let* ((arguments (list
+    (let* ((local-directory (assoc-ref opts 'read-path))
+           (arguments (list
                        package-name
                        #:include-test-dependencies?
                        (assoc-ref opts 'include-test-dependencies?)
-                       #:port (if (assoc-ref opts 'read-from-stdin?)
-                                  (current-input-port)
-                                  #f)
+                       #:port
+                       (cond
+                        ((assoc-ref opts 'read-from-stdin?)
+                         (current-input-port))
+                        (local-directory
+                         (open-file-input-port
+                          (string-append local-directory
+                                         "/" package-name ".cabal")))
+                        (else #f))
+                       #:source
+                       `(local-file ,local-directory
+                                    ,package-name
+                                    #:recursive? #t
+                                    #:select? ,(cond
+                                                ((git-repository? local-directory)
+                                                 'git-predicate)
+                                                ((hg-repository? local-directory)
+                                                 'hg-predicate)
+                                                (else '(const #t))))
                        #:cabal-environment
                        (assoc-ref opts 'cabal-environment)))
            (sexp (if (assoc-ref opts 'recursive)
                      ;; Recursive import
                      (map (match-lambda
-                            ((and ('package ('name name) . rest) pkg)
-                             `(define-public ,(string->symbol name)
-                                ,pkg))
-                            (_ #f))
+                           ((and ('package ('name name) . rest) pkg)
+                            `(define-public ,(string->symbol name)
+                               ,pkg))
+                           (_ #f))
                           (apply hackage-recursive-import arguments))
                      ;; Single import
                      (apply hackage->guix-package arguments))))
-- 
2.32.0
?