Hi Guix,

Nix flake has a convenient URL-like syntax to represent flake references and I
wonder if something similar can be implemented in Guix.  I think one approach is
to transform .guix-channel into a channels.scm, and to do so will require more
information to be included in .guix-channel.  In this mail I'll explain why.


Here's an example of Nix flake's syntax[1]: you can build and run PatchELF from
the development repository:

--8<---------------cut here---------------start------------->8---
nix shell git+https://github.com/NixOS/patchelf#patchelf --command patchelf 
--help
nix shell 
git+https://github.com/NixOS/patchelf?ref=master&rev=3e996dbef1fa0658012f8dd290bddcf0302acade#patchelf
 --command patchelf --help
--8<---------------cut here---------------end--------------->8---

This works because PatchELF provides a flake.nix[2] in its repository root to
specify its inputs and outputs, and what we get is the outputs:

--8<---------------cut here---------------start------------->8---
{
  description = "A tool for modifying ELF executables and libraries";

  inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";

  # dev tooling
  inputs.<...>

  outputs = <...>
}
--8<---------------cut here---------------end--------------->8---

PatchELF flake specifies Nixpkgs as its input, here
‘github:NixOS/nixpkgs/nixpkgs-unstable’ is similar to
‘git+https://github.com/NixOS/nixpkgs?ref=nixpkgs-unstable’, but is specialized
and works more efficient for GitHub.

Nixpkgs also provides a flake.nix in its repository root, which specifies
outputs with no inputs (it doesn't depend on other flakes).

So we can know how that syntax works: the repository specifies its dependencies
(inputs and outputs) in a well-known location (flake.nix in repository root), so
we can get enough information after knowing the repository content.


In Guix we specify dependencies via a channels.scm and since recently we can
fetch it from network:

--8<---------------cut here---------------start------------->8---
guix time-machine -C 
https://ci.guix.gnu.org/eval/latest/channels.scm?spec=master -- shell patchelf 
-- patchelf --help
--8<---------------cut here---------------end--------------->8---

Additionally, channels can specify their inputs (‘dependencies’, with the main
Guix channel implicitly) and outputs (‘news-file’, ‘directory’) in a metadata
file named ‘.guix-channel’[3], in the repository root.  Yes, in the repository
root, .guix-channel in the repository root, a well-known location!

So we actually have met the minimum requirements, we can specify dependencies
and we have a well-known location.  What's left is to implement it.


The natural approach I can think of is to use the existing interfaces and
transform .guix-channel into channels.scm, so we can do something like

--8<---------------cut here---------------start------------->8---
guix time-machine -C git+https://example.com/channel -- shell patchelf -- 
patchelf --help
--8<---------------cut here---------------end--------------->8---

Then I realized that .guix-channel doesn't contain enough information for the
channel itself.

Consider the following channels.scm, with all available fields filled in for
demonstration:
--8<---------------cut here---------------start------------->8---
(list (channel
       (name 'guix)
       (url "https://git.guix.gnu.org/guix.git";)
       (branch "master")
       (commit "02c5f415db656148afa498bae8aa5a6c8b15c615")
       (introduction
        (make-channel-introduction
         "9edb3f66fd807b096b48283debdcddccfea34bad"
         (openpgp-fingerprint
          "BBB0 2DDF 2CEA F6A8 0D1D  E643 A2A0 6DF2 A33A 54FA"))))
      (channel
       (name 'example)
       (url "https://example.com/channel";)
       (branch "trunk")
       (commit "5ca733f083ec59ea01964f02540655d8c533319b")
       (introduction
        (make-channel-introduction
         "3eca3dd8bf4c1d65f5c5a43c00ee5299b9580b6e"
         (openpgp-fingerprint
          "B472 C7FB D834 1922 60EB  3039 E09C D764 A177 711D")))))
--8<---------------cut here---------------end--------------->8---

Then the example channel would have the following .guix-channel, with all
available fields filled in for demonstration:
--8<---------------cut here---------------start------------->8---
(channel
  (version 0)
  (url "https://example.com/channel";)
  (keyring-reference "keyring")
  (news-file "NEWS")
  (directory "modules")
  (dependencies
   (channel
     (name guix)
     (url "https://git.guix.gnu.org/guix.git";)
     (branch "master")
     (commit "02c5f415db656148afa498bae8aa5a6c8b15c615")
     (introduction
      (channel-introduction
       (version 0)
       (commit "a8883b58dc82e167c96506cf05095f37c2c2c6cd")
       (signer "CABB A931 C0FF EEC6 900D  0CFB 090B 1199 3D9A EBB5"))))))
--8<---------------cut here---------------end--------------->8---

branch, commit, and introduction are missing for the channel itself.  So
information in .guix-channel alone is insufficient to construct the equivalent
channels.scm.


As a result, I consider it's useful to add more information into .guix-channel.
It can be a prerequisite for the convenient URL-like syntax, and ability to
construct a channels.scm from .guix-channel may enable more tooling as well.

WDYT?


Thanks

[1]: 
https://nix.dev/manual/nix/2.34/command-ref/new-cli/nix3-flake#flake-references
[2]: https://github.com/NixOS/patchelf/blob/master/flake.nix
[3]:
https://guix.gnu.org/manual/1.5.0/en/html_node/Package-Modules-in-a-Sub_002ddirectory.html
https://guix.gnu.org/manual/1.5.0/en/html_node/Declaring-Channel-Dependencies.html
https://guix.gnu.org/manual/1.5.0/en/html_node/Specifying-Channel-Authorizations.html
https://guix.gnu.org/manual/1.5.0/en/html_node/Primary-URL.html
https://guix.gnu.org/manual/1.5.0/en/html_node/Writing-Channel-News.html

Reply via email to