1
0
mirror of https://git.savannah.gnu.org/git/guix.git synced 2026-07-25 23:09:27 +02:00

Compare commits

...

5 Commits

Author SHA1 Message Date
Igorj Gorjaĉev 7b5f2d456b gnu: Add elixir-mix-audit.
* gnu/packages/elixir-xyz.scm (elixir-mix-audit): New variable.

Closes: https://codeberg.org/guix/guix/pulls/3524
Change-Id: I1d4565135a6d4b67046c17660573849493809e1c
Signed-off-by: Giacomo Leidi <therewasa@fishinthecalculator.me>
2026-04-11 17:47:14 +02:00
Igorj Gorjaĉev e1e28adb79 gnu: Add elixir-yaml-elixir.
* gnu/packages/elixir-xyz.scm (elixir-yaml-elixir): New variable.

Change-Id: I47e3bd31eac50699a5bccd1d515a4117ffb37563
Signed-off-by: Giacomo Leidi <therewasa@fishinthecalculator.me>
2026-04-11 17:47:14 +02:00
Igorj Gorjaĉev ea66f97ff3 gnu: Add elixir-depscheck.
* gnu/packages/elixir-xyz.scm (elixir-depscheck): New variable.

Change-Id: I7bb81fc7ed8fc068eedb1052b1d7891abfa9bbea
Signed-off-by: Giacomo Leidi <therewasa@fishinthecalculator.me>
2026-04-11 17:47:14 +02:00
Igorj Gorjaĉev 76ac03cb0b build-system: mix: Add support for importing deps from 'mix.lock'.
* guix/import/mix.scm: New file.
* guix/import/mix/mix-lock.scm: New file.
* guix/scripts/import/mix.scm: New file.
* tests/import/mix.scm: New file.
* Makefile.am (MODULES, SCM_TESTS): Register them.
* etc/teams.scm (beam): Likewise.
* gnu/packages/beam-apps.scm: New file.
* gnu/packages/beam-packages.scm: New file.
* gnu/packages/beam-sources.scm: New file.
* gnu/local.mk (GNU_SYSTEM_MODULES): Register them.
* etc/teams.scm (beam): Likewise.
* guix/build-system/mix.scm (define-mix-inputs): New macro.
(beam-name->package-name, hexpm-source, mix-inputs): New procedures.
(mix-build): Add new variables.
* guix/build/mix-build-system.scm (unpack-vendorize,
symlink-vendorize, beam-package?): New procedures.
(%standard-phases): Add new phases.
(build, check, install): Add vendoring support.
(%elixir-prefix, %beam-prefix, %vendorize-env-var): Add new symbols.
(strip-prefix, package-name->elixir-name): Add support for beam-prefixed
packages.
* guix/scripts/import.scm (process-args): Add 'mix' importer.
* etc/teams.scm (beam)<#:description>: Add Mix importer mention.
* etc/teams.scm (beam)<#:scope>: Add "tests/import/hexpm.scm".
* CODEOWNERS: Regenerate file.
* guix/import/hexpm.scm (dependencies->package-names,
hexpm->guix-package): Add optional mix-inputs support.
* guix/scripts/import/hexpm.scm (show-help, %options,
parse-options): Likewise.
* tests/import/hexpm.scm: Likewise.
* guix/import/hexpm.scm (hexpm->guix-package): Fix typo.
* doc/guix.texi: Add initial documentation for mix importer and
new option for hexpm importer.
* doc/guix-cookbook.texi: Add example of packaging Elixir app.

Change-Id: I5d11f8be111963fbac2fd6ab5fd0bd644f9488b0
Signed-off-by: Giacomo Leidi <therewasa@fishinthecalculator.me>
2026-04-11 17:47:09 +02:00
Igorj Gorjaĉev f88a63b636 gnu: elixir: Add vendoring support.
* gnu/packages/elixir.scm (elixir): Add vendoring support.
* gnu/packages/patches/elixir-vendoring-support.patch: New file.
* gnu/local.mk (dist_patch_DATA): Register it.

Change-Id: Id295ac66684c724ac799878ec58d84617bf9a5be
Signed-off-by: Giacomo Leidi <therewasa@fishinthecalculator.me>
2026-04-11 17:46:40 +02:00
22 changed files with 1214 additions and 64 deletions
+6
View File
@@ -13,6 +13,7 @@ gnu/packages/fluidplug\.scm @guix/audio
gnu/packages/music\.scm @guix/audio gnu/packages/music\.scm @guix/audio
gnu/packages/xiph\.scm @guix/audio gnu/packages/xiph\.scm @guix/audio
gnu/packages/beam-.+\.scm$ @guix/beam
gnu/packages/elixir(-.+|)\.scm$ @guix/beam gnu/packages/elixir(-.+|)\.scm$ @guix/beam
guix/build/mix-build-system\.scm @guix/beam guix/build/mix-build-system\.scm @guix/beam
guix/build-system/mix\.scm @guix/beam guix/build-system/mix\.scm @guix/beam
@@ -20,7 +21,12 @@ gnu/packages/erlang(-.+|)\.scm$ @guix/beam
guix/build/rebar-build-system\.scm @guix/beam guix/build/rebar-build-system\.scm @guix/beam
guix/build-system/rebar\.scm @guix/beam guix/build-system/rebar\.scm @guix/beam
guix/import/hexpm\.scm @guix/beam guix/import/hexpm\.scm @guix/beam
guix/import/mix\.scm @guix/beam
guix/import/mix/mix-lock\.scm @guix/beam
guix/scripts/import/hexpm\.scm @guix/beam guix/scripts/import/hexpm\.scm @guix/beam
guix/scripts/import/mix\.scm @guix/beam
tests/import/hexpm\.scm @guix/beam
tests/import/mix\.scm @guix/beam
gnu/packages/bioinformatics\.scm @guix/bioinformatics gnu/packages/bioinformatics\.scm @guix/bioinformatics
+5
View File
@@ -22,6 +22,7 @@
# Copyright © 2024 gemmaro <gemmaro.dev@gmail.com> # Copyright © 2024 gemmaro <gemmaro.dev@gmail.com>
# Copyright © 2025 Brice Waegeneire <brice@waegenei.re> # Copyright © 2025 Brice Waegeneire <brice@waegenei.re>
# Copyright © 2025 Florian Pelz <pelzflorian@pelzflorian.de> # Copyright © 2025 Florian Pelz <pelzflorian@pelzflorian.de>
# Copyright © 2025 Igorj Gorjaĉev <igor@goryachev.org>
# #
# This file is part of GNU Guix. # This file is part of GNU Guix.
# #
@@ -320,6 +321,8 @@ MODULES = \
guix/import/launchpad.scm \ guix/import/launchpad.scm \
guix/import/luanti.scm \ guix/import/luanti.scm \
guix/import/minetest.scm \ guix/import/minetest.scm \
guix/import/mix.scm \
guix/import/mix/mix-lock.scm \
guix/import/nuget.scm \ guix/import/nuget.scm \
guix/import/npm-binary.scm \ guix/import/npm-binary.scm \
guix/import/opam.scm \ guix/import/opam.scm \
@@ -377,6 +380,7 @@ MODULES = \
guix/scripts/import/json.scm \ guix/scripts/import/json.scm \
guix/scripts/import/luanti.scm \ guix/scripts/import/luanti.scm \
guix/scripts/import/minetest.scm \ guix/scripts/import/minetest.scm \
guix/scripts/import/mix.scm \
guix/scripts/import/npm-binary.scm \ guix/scripts/import/npm-binary.scm \
guix/scripts/import/nuget.scm \ guix/scripts/import/nuget.scm \
guix/scripts/import/opam.scm \ guix/scripts/import/opam.scm \
@@ -577,6 +581,7 @@ SCM_TESTS = \
tests/import/hackage.scm \ tests/import/hackage.scm \
tests/import/hexpm.scm \ tests/import/hexpm.scm \
tests/import/luanti.scm \ tests/import/luanti.scm \
tests/import/mix.scm \
tests/import/npm-binary.scm \ tests/import/npm-binary.scm \
tests/import/nuget.scm \ tests/import/nuget.scm \
tests/import/opam.scm \ tests/import/opam.scm \
+105
View File
@@ -29,6 +29,7 @@ Copyright @copyright{} 2025 45mg@*
Copyright @copyright{} 2023 Marek Felšöci@* Copyright @copyright{} 2023 Marek Felšöci@*
Copyright @copyright{} 2023 Konrad Hinsen@* Copyright @copyright{} 2023 Konrad Hinsen@*
Copyright @copyright{} 2023 Philippe Swartvagher@* Copyright @copyright{} 2023 Philippe Swartvagher@*
Copyright @copyright{} 2026 Igorj Gorjaĉev@*
Permission is granted to copy, distribute and/or modify this document Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.3 or under the terms of the GNU Free Documentation License, Version 1.3 or
@@ -140,6 +141,7 @@ Programmable and automated package definition
Packaging Workflows Packaging Workflows
* Packaging Rust Crates:: * Packaging Rust Crates::
* Packaging Elixir Applications::
Packaging Rust Crates Packaging Rust Crates
@@ -1632,6 +1634,7 @@ systems, serving as extensions to the concise packaging guidelines
@menu @menu
* Packaging Rust Crates:: * Packaging Rust Crates::
* Packaging Elixir Applications::
@end menu @end menu
@node Packaging Rust Crates @node Packaging Rust Crates
@@ -1987,6 +1990,108 @@ method, one of the most popular choices for Traditional Chinese users.")
(license license:lgpl2.1+))) (license license:lgpl2.1+)))
@end lisp @end lisp
@node Packaging Elixir Applications
@subsection Packaging Elixir Applications
In preparation, add the following packages to your environment:
@example
$ guix shell elixir elixir-depscheck elixir-mix-audit
@end example
In this example, we package @uref{https://livebook.dev, livebook},
which is an interactive, web-based notebook environment for writing,
running, and sharing Elixir code with rich documentation and
visualizations.
@enumerate
@item
We retrieve the @code{livebook} source code with the latest version
from the corresponding @code{git} repository:
@example
$ git clone --branch v0.18.2 --depth 1 \
https://github.com/livebook-dev/livebook
@end example
We should prepare the following definiton for this package (the suggested
location for this definition should be @code{gnu/packages/beam-packages.scm}
or up to your mind):
@lisp
(define-public livebook
(package
(name "livebook")
(version "0.18.2")
(source
(origin
(method git-fetch)
(uri (git-reference
(url "https://github.com/livebook-dev/livebook")
(commit (string-append "v" version))))
(file-name (git-file-name name version))
(sha256
(base32
"1pq227nabslr7gh4qvg24wj4320djc0vrh6x6l23g3468x6znxjm"))))
(build-system mix-build-system)
(arguments
(list
#:tests? #f ; TODO: make them work a little bit later
#:vendorize? #t
#:phases
#~(modify-phases %standard-phases
(replace 'install
(lambda* (#:key outputs #:allow-other-keys)
(let ((out (assoc-ref outputs "out")))
(copy-recursively "_build/prod/rel/livebook/"
out)))))))
(inputs (mix-inputs 'livebook))
(synopsis "Web application for writing code notebooks")
(description "This package provides @code{Livebook}, a web application
for writing interactive and collaborative code notebooks.")
(home-page "https://livebook.dev/")
(license license:asl2.0)))
@end lisp
The identifier used to invoke @code{mix-inputs}, in this case the scheme
symbol @code{'livebook}, must be unique, usually matching the variable name
of the package.
@item
Navigate to the unpacked directory, then run the following commands:
@example
$ mix deps.get
$ mix deps.audit
$ mix depscheck --verbose
@end example
@command{mix deps.audit} checks known vulnerabilities and @command{mix
depscheck --verbose} checks licenses, for all the dependencies. We must
have an acceptable output (i.e. message ``No vulnerabilities found.'') of
@command{mix deps.audit} and ensure all dependencies are licensed with our
supported licenses (@pxref{Defining Packages,,, guix, GNU Guix Reference Manual}).
@item
Import dependencies from the lockfile:
@example
$ guix import --insert=gnu/packages/beam-packages.scm \
mix --lockfile=/path/to/mix.lock livebook
# or:
$ guix import -i gnu/packages/beam-packages.scm \
mix -f /path/to/mix.lock livebook
@end example
After that the package could be build by using the following command:
@example
$ guix build livebook
@end example
@end enumerate
@c ********************************************************************* @c *********************************************************************
@node System Configuration @node System Configuration
+26
View File
@@ -151,6 +151,7 @@ Copyright @copyright{} 2025 Noé Lopez@*
Copyright @copyright{} 2026 David Elsing@* Copyright @copyright{} 2026 David Elsing@*
Copyright @copyright{} 2026 Nguyễn Gia Phong@* Copyright @copyright{} 2026 Nguyễn Gia Phong@*
Copyright @copyright{} 2026 Yarl Baudig@* Copyright @copyright{} 2026 Yarl Baudig@*
Copyright @copyright{} 2026 Igorj Gorjaĉev@*
Permission is granted to copy, distribute and/or modify this document Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.3 or under the terms of the GNU Free Documentation License, Version 1.3 or
@@ -15388,6 +15389,31 @@ Additional options include:
Traverse the dependency graph of the given upstream package recursively Traverse the dependency graph of the given upstream package recursively
and generate package expressions for all those packages that are not yet and generate package expressions for all those packages that are not yet
in Guix. in Guix.
@item --mix-inputs
@itemx -m
Use vendored @code{mix-inputs} for @code{input} field instead of common
dependencies.
@end table
@item mix
@cindex mix
Import metadata from the @file{mix.lock}, Elixir's
@uref{https://hexdocs.pm/elixir/introduction-to-mix.html, mix} lock file,
as in this example:
@example
guix import mix -f mix.lock yourapp
@end example
Mandatory options are:
@table @code
@item --lockfile=@var{file}
@itemx -f @var{file}
@option{--lockfile} must be a @file{mix.lock} file.
@xref{Packaging Elixir Applications,,, guix-cookbook, GNU Guix Cookbook}, for
packaging workflow utilizing it.
@end table @end table
@end table @end table
+9 -3
View File
@@ -482,15 +482,21 @@ already exists. Lookup team IDs among CURRENT-TEAMS."
#:name "Erlang/Elixir/BEAM team" #:name "Erlang/Elixir/BEAM team"
#:description "The virtual machine at the core of the Erlang Open #:description "The virtual machine at the core of the Erlang Open
Telecom Platform (OTP), Erlang and Elxir languages and packages, development Telecom Platform (OTP), Erlang and Elxir languages and packages, development
of Rebar and Mix build systems and Hex.pm importer." of Rebar and Mix build systems, Hex.pm and Mix importers."
#:scope (list (make-regexp* "^gnu/packages/elixir(-.+|)\\.scm$") #:scope (list (make-regexp* "^gnu/packages/beam-.+\\.scm$")
(make-regexp* "^gnu/packages/elixir(-.+|)\\.scm$")
"guix/build/mix-build-system.scm" "guix/build/mix-build-system.scm"
"guix/build-system/mix.scm" "guix/build-system/mix.scm"
(make-regexp* "^gnu/packages/erlang(-.+|)\\.scm$") (make-regexp* "^gnu/packages/erlang(-.+|)\\.scm$")
"guix/build/rebar-build-system.scm" "guix/build/rebar-build-system.scm"
"guix/build-system/rebar.scm" "guix/build-system/rebar.scm"
"guix/import/hexpm.scm" "guix/import/hexpm.scm"
"guix/scripts/import/hexpm.scm"))) "guix/import/mix.scm"
"guix/import/mix/mix-lock.scm"
"guix/scripts/import/hexpm.scm"
"guix/scripts/import/mix.scm"
"tests/import/hexpm.scm"
"tests/import/mix.scm")))
(define-team bioinformatics (define-team bioinformatics
(team 'bioinformatics (team 'bioinformatics
+5
View File
@@ -75,6 +75,7 @@
# Copyright © 2025 Nigko Yerden <nigko.yerden@gmail.com> # Copyright © 2025 Nigko Yerden <nigko.yerden@gmail.com>
# Copyright © 2025 Cayetano Santos <csantosb@inventati.org> # Copyright © 2025 Cayetano Santos <csantosb@inventati.org>
# Copyright © 2025 bdunahu <bdunahu@operationnull.com> # Copyright © 2025 bdunahu <bdunahu@operationnull.com>
# Copyright © 2025 Igorj Gorjaĉev <igor@goryachev.org>
# #
# This file is part of GNU Guix. # This file is part of GNU Guix.
# #
@@ -175,6 +176,9 @@ GNU_SYSTEM_MODULES = \
%D%/packages/bash.scm \ %D%/packages/bash.scm \
%D%/packages/batik.scm \ %D%/packages/batik.scm \
%D%/packages/bdw-gc.scm \ %D%/packages/bdw-gc.scm \
%D%/packages/beam-apps.scm \
%D%/packages/beam-packages.scm \
%D%/packages/beam-sources.scm \
%D%/packages/benchmark.scm \ %D%/packages/benchmark.scm \
%D%/packages/bioconductor.scm \ %D%/packages/bioconductor.scm \
%D%/packages/bioinformatics.scm \ %D%/packages/bioinformatics.scm \
@@ -1228,6 +1232,7 @@ dist_patch_DATA = \
%D%/packages/patches/elfutils-tests-ptrace.patch \ %D%/packages/patches/elfutils-tests-ptrace.patch \
%D%/packages/patches/elixir-httpoison-tag-network-dependent-test-cases.patch \ %D%/packages/patches/elixir-httpoison-tag-network-dependent-test-cases.patch \
%D%/packages/patches/elixir-path-length.patch \ %D%/packages/patches/elixir-path-length.patch \
%D%/packages/patches/elixir-vendoring-support.patch \
%D%/packages/patches/elm-ghc9.2.patch \ %D%/packages/patches/elm-ghc9.2.patch \
%D%/packages/patches/exaile-gstreamer-1.28.patch \ %D%/packages/patches/exaile-gstreamer-1.28.patch \
%D%/packages/patches/python-treelib-remove-python2-compat.patch \ %D%/packages/patches/python-treelib-remove-python2-compat.patch \
+25
View File
@@ -0,0 +1,25 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2025 Igorj Gorjaĉev <igor@goryachev.org>
;;;
;;; This file is part of GNU Guix.
;;;
;;; GNU Guix is free software; you can redistribute it and/or modify it
;;; under the terms of the GNU General Public License as published by
;;; the Free Software Foundation; either version 3 of the License, or (at
;;; your option) any later version.
;;;
;;; GNU Guix is distributed in the hope that it will be useful, but
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;;; GNU General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
(define-module (gnu packages beam-apps)
#:use-module ((guix licenses) #:prefix license:)
#:use-module (guix gexp)
#:use-module (guix packages)
#:use-module (guix download)
#:use-module (guix git-download)
#:use-module (guix build-system mix))
+43
View File
@@ -0,0 +1,43 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2025 Igorj Gorjaĉev <igor@goryachev.org>
;;;
;;; This file is part of GNU Guix.
;;;
;;; GNU Guix is free software; you can redistribute it and/or modify it
;;; under the terms of the GNU General Public License as published by
;;; the Free Software Foundation; either version 3 of the License, or (at
;;; your option) any later version.
;;;
;;; GNU Guix is distributed in the hope that it will be useful, but
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;;; GNU General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
(define-module (gnu packages beam-packages)
#:use-module (guix gexp)
#:use-module (guix packages)
#:use-module (guix download)
#:use-module (guix git-download)
#:use-module (guix build-system mix)
#:use-module (gnu packages beam-sources)
#:export (lookup-mix-inputs))
;;;
;;; This file is managed by guix import. Do NOT add definitions manually.
;;;
;;; BEAM libraries fetched from hex.pm.
;;;
(define aaaa-separator 'begin-of-beam-packages)
(define cccc-separator 'end-of-beam-packages)
;;;
;;; Mix inputs.
;;;
(define-mix-inputs lookup-mix-inputs)
+29
View File
@@ -0,0 +1,29 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2025 Igorj Gorjaĉev <igor@goryachev.org>
;;;
;;; This file is part of GNU Guix.
;;;
;;; GNU Guix is free software; you can redistribute it and/or modify it
;;; under the terms of the GNU General Public License as published by
;;; the Free Software Foundation; either version 3 of the License, or (at
;;; your option) any later version.
;;;
;;; GNU Guix is distributed in the hope that it will be useful, but
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;;; GNU General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
(define-module (gnu packages beam-sources)
#:use-module (guix gexp)
#:use-module (guix packages)
#:use-module (guix download)
#:use-module (guix git-download)
#:use-module (guix build-system mix))
;;;
;;; BEAM libraries requiring modification.
;;; These packages are hidden, as they are not interesting to users.
;;;
+71 -1
View File
@@ -1,6 +1,6 @@
;;; GNU Guix --- Functional package management for GNU ;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2023 Pierre-Henry Fröhring <phfrohring@deeplinks.com> ;;; Copyright © 2023 Pierre-Henry Fröhring <phfrohring@deeplinks.com>
;;; Copyright © 2024 Igor Goryachev <igor@goryachev.org> ;;; Copyright © 2024, 2026 Igorj Gorjaĉev <igor@goryachev.org>
;;; Copyright © 2025 Giacomo Leidi <therewasa@fishinthecalculator.me> ;;; Copyright © 2025 Giacomo Leidi <therewasa@fishinthecalculator.me>
;;; ;;;
;;; This file is part of GNU Guix. ;;; This file is part of GNU Guix.
@@ -24,6 +24,7 @@
#:use-module (gnu packages linux) #:use-module (gnu packages linux)
#:use-module (gnu packages compression) #:use-module (gnu packages compression)
#:use-module (gnu packages base) #:use-module (gnu packages base)
#:use-module (gnu packages erlang)
#:use-module (gnu packages erlang-xyz) #:use-module (gnu packages erlang-xyz)
#:use-module (gnu packages gettext) #:use-module (gnu packages gettext)
#:use-module (gnu packages) #:use-module (gnu packages)
@@ -423,6 +424,25 @@ implementing function decorators for Elixir.")
(home-page "https://hexdocs.pm/decorator/") (home-page "https://hexdocs.pm/decorator/")
(license license:expat))) (license license:expat)))
(define-public elixir-depscheck
(package
(name "elixir-depscheck")
(version "1.0.11")
(source
(origin
(method url-fetch)
(uri (hexpm-uri "depscheck" version))
(sha256
(base32 "1v33ml2i19s59518j9031bsvipbf4xxr4xk49qx6xs3qby0018aw"))))
(build-system mix-build-system)
(synopsis "Checking dependency license compatibility in Elixir projects")
(description "This package provides @code{elixir-depscheck}, a @code{CI/CD}
tool for checking dependency license compatibility in Elixir projects. Reads
license information from local hex metadata files and validates compatibility
with your project's license using industry-standard rules.")
(home-page "https://hexdocs.pm/depscheck/")
(license license:expat)))
(define-public elixir-erlex (define-public elixir-erlex
(package (package
(name "elixir-erlex") (name "elixir-erlex")
@@ -731,6 +751,28 @@ Elixir.")
(home-page "https://hexdocs.pm/mimic/") (home-page "https://hexdocs.pm/mimic/")
(license license:asl2.0))) (license license:asl2.0)))
(define-public elixir-mix-audit
(package
(name "elixir-mix-audit")
(version "2.1.5")
(source
(origin
(method url-fetch)
(uri (hexpm-uri "mix_audit" version))
(sha256
(base32 "0s9dnk42n5665s6l22qf05x63ly11n37am2kmybzccns4672kyc7"))))
(build-system mix-build-system)
(propagated-inputs
(list elixir-jason
elixir-yaml-elixir))
(synopsis "Scanning Mix dependencies for security vulnerabilities")
(description "This package provides @code{elixir-mix-audit}, a
@code{mix deps.audit} task to scan @code{Mix} dependencies for security
vulnerabilities. It draw its inspiration from tools like npm audit and
bundler-audit.")
(home-page "https://hexdocs.pm/mix_audit/")
(license license:bsd-3)))
(define-public elixir-mox (define-public elixir-mox
(package (package
(name "elixir-mox") (name "elixir-mox")
@@ -1227,6 +1269,34 @@ provides a polyfill for @code{dbg} which was introduced in Elixir 1.14.")
(home-page "https://hexdocs.pm/verbs/") (home-page "https://hexdocs.pm/verbs/")
(license license:expat))) (license license:expat)))
(define-public elixir-yaml-elixir
(package
(name "elixir-yaml-elixir")
(version "2.12.0")
(source
(origin
(method url-fetch)
(uri (hexpm-uri "yaml_elixir" version))
(sha256
(base32 "1ihknd9qy8y533zd150ch2yag2h895hsp86wamqpm4dcgfpaqsya"))))
(build-system mix-build-system)
(arguments
(list
#:phases
#~(modify-phases %standard-phases
(add-after 'unpack 'fix-yamerl-hrl-path
(lambda _
(substitute* "lib/yaml_elixir/records.ex"
(("internal\\/yamerl_constr\\.hrl")
"yamerl_constr.hrl")))))))
(propagated-inputs
(list erlang-yamerl))
(synopsis "YAML parser for Elixir based on native Erlang implementation")
(description "This package provides @code{elixir-yaml-elixir}, a @code{YAML}
parser for @code{Elixir} based on native @code{Erlang} implementation.")
(home-page "https://hexdocs.pm/yaml_elixir/")
(license license:expat)))
(define-public elixir-zest (define-public elixir-zest
(package (package
(name "elixir-zest") (name "elixir-zest")
+2 -1
View File
@@ -51,7 +51,8 @@
(file-name (git-file-name name version)) (file-name (git-file-name name version))
(sha256 (sha256
(base32 "1i10a5d7mlcrav47k7qirqvrqn2kbl5265fbcp8fzavr86xz67m6")) (base32 "1i10a5d7mlcrav47k7qirqvrqn2kbl5265fbcp8fzavr86xz67m6"))
(patches (search-patches "elixir-path-length.patch")))) (patches (search-patches "elixir-path-length.patch"
"elixir-vendoring-support.patch"))))
(build-system gnu-build-system) (build-system gnu-build-system)
(arguments (arguments
(list (list
@@ -0,0 +1,56 @@
Author: Igorj Gorjaĉev <igor@goryachev.org>
Date: Wed Oct 22 10:10:13 2025 +0300
vendoring support for guix
diff --git a/lib/mix/lib/mix/dep/loader.ex b/lib/mix/lib/mix/dep/loader.ex
index e47bfc556..0ddd49fe5 100644
--- a/lib/mix/lib/mix/dep/loader.ex
+++ b/lib/mix/lib/mix/dep/loader.ex
@@ -198,6 +198,10 @@ defp with_scm_and_app(app, req, opts, original, locked?) do
)
end
+ scm = Mix.Guix.scm(scm)
+ req = Mix.Guix.req(req)
+ opts = Mix.Guix.opts(opts, app)
+
%Mix.Dep{
scm: scm,
app: app,
diff --git a/lib/mix/lib/mix/guix.ex b/lib/mix/lib/mix/guix.ex
new file mode 100644
index 000000000..9c821704c
--- /dev/null
+++ b/lib/mix/lib/mix/guix.ex
@@ -0,0 +1,30 @@
+defmodule Mix.Guix do
+ @moduledoc false
+
+ @guix_vendorize "GUIX_MIX_VENDOR_DIR"
+
+ def scm(scm), do: (vendorize?() && Mix.SCM.Path) || scm
+
+ def req(req), do: (vendorize?() && nil) || req
+
+ def opts(opts, app) do
+ if vendorize?() do
+ if Keyword.has_key?(opts, :path) do
+ opts
+ else
+ dep_dir = vendor_dep_dir(app)
+
+ [path: dep_dir, dest: dep_dir] ++
+ Keyword.drop(opts, [:hex, :override, :repo, :lock, :dest])
+ end
+ else
+ opts
+ end
+ end
+
+ defp vendorize?, do: not is_nil(vendor_dir())
+
+ defp vendor_dir, do: System.get_env(@guix_vendorize)
+
+ defp vendor_dep_dir(name), do: "#{vendor_dir()}/#{name}"
+end
+58 -1
View File
@@ -1,6 +1,7 @@
;;; GNU Guix --- Functional package management for GNU ;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2023 Pierre-Henry Fröhring <contact@phfrohring.com> ;;; Copyright © 2023 Pierre-Henry Fröhring <contact@phfrohring.com>
;;; Copyright © 2025 Giacomo Leidi <therewasa@fishinthecalculator.me> ;;; Copyright © 2025 Giacomo Leidi <therewasa@fishinthecalculator.me>
;;; Copyright © 2025 Igorj Gorjaĉev <igor@goryachev.org>
;;; ;;;
;;; This file is part of GNU Guix. ;;; This file is part of GNU Guix.
;;; ;;;
@@ -28,7 +29,10 @@
#:use-module (guix build mix-build-system) #:use-module (guix build mix-build-system)
#:use-module (guix build-system gnu) #:use-module (guix build-system gnu)
#:use-module (guix build-system) #:use-module (guix build-system)
#:use-module (guix diagnostics)
#:use-module (guix download)
#:use-module (guix gexp) #:use-module (guix gexp)
#:use-module (guix i18n)
#:use-module (guix monads) #:use-module (guix monads)
#:use-module (guix packages) #:use-module (guix packages)
#:use-module (guix search-paths) #:use-module (guix search-paths)
@@ -37,7 +41,12 @@
#:use-module (ice-9 match) #:use-module (ice-9 match)
#:use-module (srfi srfi-1) #:use-module (srfi srfi-1)
#:use-module (srfi srfi-26) #:use-module (srfi srfi-26)
#:export (mix-build-system hexpm-uri)) #:export (mix-build-system
hexpm-uri
beam-name->package-name
hexpm-source
define-mix-inputs
mix-inputs))
(define (default-elixir-hex) (define (default-elixir-hex)
(@* (gnu packages elixir) elixir-hex)) (@* (gnu packages elixir) elixir-hex))
@@ -64,6 +73,48 @@ See: https://github.com/hexpm/specifications/blob/main/endpoints.md"
strip-prefix) strip-prefix)
name)) name))
(define (beam-name->package-name name)
(downstream-package-name "beam-" name))
;; NOTE: Only use this procedure in (gnu packages beam-packages).
(define* (hexpm-source package-name hexpm-name hexpm-version hexpm-hash
#:key (patches '()) (snippet #f))
(origin
(method url-fetch)
(uri (hexpm-uri hexpm-name hexpm-version))
(file-name
(string-append "beam-" package-name "-" hexpm-version ".tar"))
(sha256 (base32 hexpm-hash))
(modules '((guix build utils)))
(patches patches)
(snippet snippet)))
(define-syntax define-mix-inputs
(syntax-rules (=>)
((_ lookup inputs ...)
(define lookup
(let ((table (make-hash-table)))
(letrec-syntax ((record
(syntax-rules (=>)
((_) #t)
((_ (name => lst) rest (... ...))
(begin
(hashq-set! table 'name (filter identity lst))
(record rest (... ...)))))))
(record inputs ...)
(lambda (name)
"Return the inputs for NAME."
(hashq-ref table name))))))))
(define* (mix-inputs name #:key (module '(gnu packages beam-packages)))
"Lookup Mix inputs for NAME defined in MODULE, return an empty list if
unavailable."
(let ((lookup (module-ref (resolve-interface module) 'lookup-mix-inputs)))
(or (lookup name)
(begin
(warning (G_ "no Mix inputs available for '~a'~%") name)
'()))))
;; A number of environment variables specific to the Mix build system are ;; A number of environment variables specific to the Mix build system are
;; reflected here. They are documented at ;; reflected here. They are documented at
;; https://hexdocs.pm/mix/Mix.html#module-environment-variables. Other ;; https://hexdocs.pm/mix/Mix.html#module-environment-variables. Other
@@ -75,6 +126,9 @@ See: https://github.com/hexpm/specifications/blob/main/endpoints.md"
source source
(tests? #t) (tests? #t)
(test-flags ''()) (test-flags ''())
(vendorize? #f)
(vendor-symlinks? #t)
(vendor-dir "guix-vendor")
(mix-path #f) ;See MIX_PATH. (mix-path #f) ;See MIX_PATH.
(mix-exs "mix.exs") ;See MIX_EXS. (mix-exs "mix.exs") ;See MIX_EXS.
(build-per-environment #t) ;See :build_per_environment. (build-per-environment #t) ;See :build_per_environment.
@@ -110,6 +164,9 @@ See: https://github.com/hexpm/specifications/blob/main/endpoints.md"
#:system #$system #:system #$system
#:tests? #$tests? #:tests? #$tests?
#:test-flags #$test-flags #:test-flags #$test-flags
#:vendorize? #$vendorize?
#:vendor-symlinks? #$vendor-symlinks?
#:vendor-dir #$vendor-dir
#:mix-path #$mix-path #:mix-path #$mix-path
#:mix-exs #$mix-exs #:mix-exs #$mix-exs
#:mix-environments '#$mix-environments #:mix-environments '#$mix-environments
+115 -22
View File
@@ -1,6 +1,6 @@
;;; GNU Guix --- Functional package management for GNU ;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2023 Pierre-Henry Fröhring <contact@phfrohring.com> ;;; Copyright © 2023 Pierre-Henry Fröhring <contact@phfrohring.com>
;;; Copyright © 2024, 2026 Igorj Gorjaĉev <igor@goryachev.org> ;;; Copyright © 2024-2026 Igorj Gorjaĉev <igor@goryachev.org>
;;; Copyright © 2024, 2025 Giacomo Leidi <therewasa@fishinthecalculator.me> ;;; Copyright © 2024, 2025 Giacomo Leidi <therewasa@fishinthecalculator.me>
;;; ;;;
;;; This file is part of GNU Guix. ;;; This file is part of GNU Guix.
@@ -48,7 +48,13 @@
VERSION are installed." VERSION are installed."
(string-append path "/lib/elixir/" version)) (string-append path "/lib/elixir/" version))
(define* (strip-prefix name #:optional (prefix "elixir-")) (define %elixir-prefix "elixir-")
(define %beam-prefix "beam-")
(define %vendorize-env-var "GUIX_MIX_VENDOR_DIR")
(define* (strip-prefix name #:optional (prefix %elixir-prefix))
"Return NAME without the prefix PREFIX." "Return NAME without the prefix PREFIX."
(if (string-prefix? prefix name) (if (string-prefix? prefix name)
(string-drop name (string-length prefix)) (string-drop name (string-length prefix))
@@ -83,9 +89,73 @@ working directory."
(define (list-directories dir) (define (list-directories dir)
"List absolute paths of directories directly under the directory DIR." "List absolute paths of directories directly under the directory DIR."
(map (cute string-append dir "/" <>) (map (cute string-append dir "/" <>)
(scandir dir (lambda (filename) (scandir
(and (not (member filename '("." ".."))) dir (lambda (filename)
(directory-exists? (string-append dir "/" filename))))))) (and (not (member filename '("." "..")))
(directory-exists? (string-append dir "/" filename)))))))
(define* (unpack-vendorize #:key vendorize? vendor-dir inputs
#:allow-other-keys)
"Unpack vendored packages."
(define (inputs->beam-inputs inputs)
"Filter using the label part from INPUTS."
(filter-map (lambda (input)
(match input
((name . file)
(and (beam-package? name) file))))
inputs))
(define (beam-input->upstream-name beam-input)
"Convert BEAM-INPUT into upstream package name."
((compose
(cute package-name->elixir-name <> %beam-prefix)
(cute substring <> 33)
basename)
beam-input))
(define (copy-or-unpack-beam-package beam-input dep-dir)
"Copy contents, if BEAM-INPUT is a checkout package, otherwise unpack it."
(or (directory-exists? dep-dir)
(if (file-is-directory? beam-input)
(copy-recursively beam-input dep-dir)
(begin
(mkdir-p dep-dir)
(invoke "sh" "-c"
(string-append "tar -xOf " beam-input
" contents.tar.gz"
" | tar -xz -C " dep-dir))))))
(and
vendorize?
(begin
(mkdir-p vendor-dir)
(setenv %vendorize-env-var (canonicalize-path vendor-dir))
(let ((beam-inputs (delete-duplicates (inputs->beam-inputs inputs))))
(unless (null? beam-inputs)
(for-each
(lambda (beam-input)
(let* ((upstream-name (beam-input->upstream-name beam-input))
(dep-dir (string-append vendor-dir "/" upstream-name)))
(copy-or-unpack-beam-package beam-input dep-dir)))
beam-inputs))))))
(define* (symlink-vendorize #:key vendorize? vendor-symlinks?
#:allow-other-keys)
(and
vendorize?
vendor-symlinks?
(let* ((vendor-dir (getenv %vendorize-env-var))
(deps-dir (list-directories vendor-dir)))
(for-each
(lambda (dep-dir)
(let ((snapshot (string-contains dep-dir "_snapshot")))
(and
snapshot
(let ((canonical
(string-drop-right
dep-dir (- (string-length dep-dir) snapshot))))
(symlink dep-dir canonical)))))
deps-dir))))
(define (beam-package? name)
(string-prefix? %beam-prefix name))
(define* (set-mix-env #:key inputs mix-path mix-exs #:allow-other-keys) (define* (set-mix-env #:key inputs mix-path mix-exs #:allow-other-keys)
"Set environment variables. "Set environment variables.
@@ -113,22 +183,32 @@ See: https://hexdocs.pm/mix/1.15.7/Mix.html#module-environment-variables"
(%elixir-version (elixir-version inputs)) (%elixir-version (elixir-version inputs))
(format #t "Elixir version: ~a~%" (%elixir-version))) (format #t "Elixir version: ~a~%" (%elixir-version)))
(define* (build #:key mix-environments #:allow-other-keys)
(define* (build #:key mix-environments vendorize?
#:allow-other-keys)
"Builds the Mix project." "Builds the Mix project."
(for-each (lambda (mix-env) (for-each (lambda (mix-env)
(setenv "MIX_ENV" mix-env) (setenv "MIX_ENV" mix-env)
(invoke "mix" "compile" "--no-deps-check" (if vendorize?
"--no-prune-code-paths")) (invoke "mix" "release")
(invoke "mix" "compile" "--no-prune-code-paths"
"--no-deps-check")))
mix-environments)) mix-environments))
(define* (check #:key (tests? #t) (test-flags '()) #:allow-other-keys) (define* (check #:key (tests? #t) (test-flags '())
vendorize?
#:allow-other-keys)
"Test the Mix project." "Test the Mix project."
(if tests? (if tests?
(begin (let ((maybe-no-deps-check-flag
(if vendorize? '() '("--no-deps-check"))))
(setenv "MIX_ENV" "test") (setenv "MIX_ENV" "test")
(apply invoke "mix" "do" "compile" "--no-deps-check" (apply invoke
"--no-prune-code-paths" "+" "test" (append '("mix" "do" "compile")
"--no-deps-check" test-flags)) maybe-no-deps-check-flag
'("--no-prune-code-paths" "+" "test")
maybe-no-deps-check-flag
test-flags)))
(format #t "tests? = ~a~%" tests?))) (format #t "tests? = ~a~%" tests?)))
(define* (remove-mix-dirs . _) (define* (remove-mix-dirs . _)
@@ -137,7 +217,7 @@ We do not want to copy them to the installation directory."
(for-each delete-file-recursively (for-each delete-file-recursively
(find-files "." (file-name-predicate "\\.mix$") #:directories? #t))) (find-files "." (file-name-predicate "\\.mix$") #:directories? #t)))
(define (package-name->elixir-name name+ver) (define* (package-name->elixir-name name+ver #:optional (prefix %elixir-prefix))
"Convert the Guix package NAME-VER to the corresponding Elixir name-version "Convert the Guix package NAME-VER to the corresponding Elixir name-version
format. Example: elixir-a-pkg-1.2.3 -> a_pkg or elixir-a-pkg-0.0.0-0.e51e36e format. Example: elixir-a-pkg-1.2.3 -> a_pkg or elixir-a-pkg-0.0.0-0.e51e36e
-> a_pkg" -> a_pkg"
@@ -146,7 +226,7 @@ format. Example: elixir-a-pkg-1.2.3 -> a_pkg or elixir-a-pkg-0.0.0-0.e51e36e
(cute string-join <> "_") (cute string-join <> "_")
(cute drop-right <> (if git-version? 2 1)) (cute drop-right <> (if git-version? 2 1))
(cute string-split <> #\-)) (cute string-split <> #\-))
(strip-prefix name+ver))) (strip-prefix name+ver prefix)))
(define* (install #:key (define* (install #:key
inputs inputs
@@ -155,13 +235,24 @@ format. Example: elixir-a-pkg-1.2.3 -> a_pkg or elixir-a-pkg-0.0.0-0.e51e36e
build-per-environment build-per-environment
#:allow-other-keys) #:allow-other-keys)
"Install build artifacts in the store." "Install build artifacts in the store."
(let* ((lib-name (package-name->elixir-name name)) (if (beam-package? name)
(lib-dir (string-append (elixir-libdir (assoc-ref outputs "out")) "/" lib-name)) (let* ((out (assoc-ref outputs "out"))
(root (getenv "MIX_BUILD_ROOT")) (excluded '("CHECKSUM" "contents.tar.gz" "environment-variables"
(env (if build-per-environment "prod" "shared"))) "metadata.config" "VERSION"))
(mkdir-p lib-dir) (files
(copy-recursively (string-append (mix-build-dir root env) "/" lib-name) lib-dir (filter
#:follow-symlinks? #t))) (lambda (f)
(not (member f (cons* "." ".." excluded))))
(scandir "."))))
(mkdir-p out)
(apply invoke "cp" "-r" (append files (list out))))
(let* ((lib-name (package-name->elixir-name name))
(lib-dir (string-append (elixir-libdir (assoc-ref outputs "out")) "/" lib-name))
(root (getenv "MIX_BUILD_ROOT"))
(env (if build-per-environment "prod" "shared")))
(mkdir-p lib-dir)
(copy-recursively (string-append (mix-build-dir root env) "/" lib-name) lib-dir
#:follow-symlinks? #t))))
(define %standard-phases (define %standard-phases
(modify-phases gnu:%standard-phases (modify-phases gnu:%standard-phases
@@ -170,6 +261,8 @@ format. Example: elixir-a-pkg-1.2.3 -> a_pkg or elixir-a-pkg-0.0.0-0.e51e36e
(add-after 'install-locale 'set-mix-env set-mix-env) (add-after 'install-locale 'set-mix-env set-mix-env)
(add-after 'set-mix-env 'set-elixir-version set-elixir-version) (add-after 'set-mix-env 'set-elixir-version set-elixir-version)
(replace 'unpack unpack) (replace 'unpack unpack)
(add-after 'unpack 'unpack-vendorize unpack-vendorize)
(add-after 'unpack-vendorize 'symlink-vendorize symlink-vendorize)
(replace 'build build) (replace 'build build)
(replace 'check check) (replace 'check check)
(add-before 'install 'remove-mix-dirs remove-mix-dirs) (add-before 'install 'remove-mix-dirs remove-mix-dirs)
+33 -26
View File
@@ -177,33 +177,37 @@ as symbols."
(define* (make-hexpm-sexp #:key name version tarball-url (define* (make-hexpm-sexp #:key name version tarball-url
home-page synopsis description license home-page synopsis description license
language build-system dependencies language build-system dependencies
mix-inputs?
#:allow-other-keys) #:allow-other-keys)
"Return the `package' s-expression for a hexpm package with the given NAME, "Return the `package' s-expression for a hexpm package with the given NAME,
VERSION, TARBALL-URL, HOME-PAGE, SYNOPSIS, DESCRIPTION, and LICENSE. The VERSION, TARBALL-URL, HOME-PAGE, SYNOPSIS, DESCRIPTION, and LICENSE. The
created package's name will stem from LANGUAGE. BUILD-SYSTEM defined the created package's name will stem from LANGUAGE. BUILD-SYSTEM defined the
build-system, and DEPENDENCIES the inputs for the package." build-system, and DEPENDENCIES or MIX-INPUTS? the inputs for the package."
(call-with-temporary-output-file (let ((package-name (hexpm-name->package-name name language)))
(lambda (temp port) (call-with-temporary-output-file
(and (url-fetch tarball-url temp) (lambda (temp port)
(values (and (url-fetch tarball-url temp)
`(package (values
(name ,(hexpm-name->package-name name language)) `(package
(version ,version) (name ,package-name)
(source (origin (version ,version)
(method url-fetch) (source (origin
(uri (hexpm-uri ,name version)) (method url-fetch)
(sha256 (base32 ,(guix-hash-url temp))))) (uri (hexpm-uri ,name version))
(build-system ,build-system) (sha256 (base32 ,(guix-hash-url temp)))))
,@(maybe-inputs (dependencies->package-names dependencies) 'inputs) (build-system ,build-system)
(synopsis ,synopsis) ,@(if mix-inputs?
(description ,(beautify-description description)) `((inputs (mix-inputs ',(string->symbol package-name))))
(home-page ,(match home-page (maybe-inputs (dependencies->package-names dependencies) 'inputs))
(() "") (synopsis ,synopsis)
(_ home-page))) (description ,(beautify-description description))
(license ,(match license (home-page ,(match home-page
(() #f) (() "")
((license) license) (_ home-page)))
(_ `(list ,@license)))))))))) (license ,(match license
(() #f)
((license) license)
(_ `(list ,@license)))))))))))
(define (strings->licenses strings) (define (strings->licenses strings)
"Convert the list of STRINGS into a list of license objects." "Convert the list of STRINGS into a list of license objects."
@@ -221,11 +225,13 @@ object, ordered from newest to oldest."
(sort (map hexpm-version-number (hexpm-versions package)) (sort (map hexpm-version-number (hexpm-versions package))
version>?)) version>?))
(define* (hexpm->guix-package package-name #:key version #:allow-other-keys) (define* (hexpm->guix-package package-name #:key version
"Fetch the metadata for PACKAGE-NAME from hexpms.io, and return the mix-inputs? #:allow-other-keys)
"Fetch the metadata for PACKAGE-NAME from hex.pm, and return the
`package' s-expression corresponding to that package, or #f on failure. `package' s-expression corresponding to that package, or #f on failure.
When VERSION is specified, attempt to fetch that version; otherwise fetch the When VERSION is specified, attempt to fetch that version; otherwise fetch the
latest version of PACKAGE-NAME." latest version of PACKAGE-NAME. It can use `inputs` with `mix-inputs` when
MIX-INPUTS? is specified."
(define package (define package
(lookup-hexpm package-name)) (lookup-hexpm package-name))
@@ -277,6 +283,7 @@ latest version of PACKAGE-NAME."
#:name package-name #:name package-name
#:version version-number #:version version-number
#:dependencies dependencies #:dependencies dependencies
#:mix-inputs? mix-inputs?
#:home-page (or (and (not (eq? docs-html-url 'null)) #:home-page (or (and (not (eq? docs-html-url 'null))
docs-html-url) docs-html-url)
;; TODO: Homepage? ;; TODO: Homepage?
+143
View File
@@ -0,0 +1,143 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2025 Igorj Gorjaĉev <igor@goryachev.org>
;;;
;;; This file is part of GNU Guix.
;;;
;;; GNU Guix is free software; you can redistribute it and/or modify it
;;; under the terms of the GNU General Public License as published by
;;; the Free Software Foundation; either version 3 of the License, or (at
;;; your option) any later version.
;;;
;;; GNU Guix is distributed in the hope that it will be useful, but
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;;; GNU General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
(define-module (guix import mix)
#:use-module (guix import mix mix-lock)
#:use-module (guix base16)
#:use-module (guix base32)
#:use-module (guix read-print)
#:use-module (guix scripts download)
#:autoload (guix utils) (find-definition-location)
#:use-module (ice-9 match)
#:use-module (ice-9 textual-ports)
#:use-module (srfi srfi-1)
#:use-module (srfi srfi-26)
#:use-module (srfi srfi-71)
#:use-module (guix build-system mix)
#:export (mix-lock->expressions
mix-inputs-from-lockfile
find-mix-inputs-location
extract-mix-inputs))
;;;
;;; Convert mix.lock to Guix sources.
;;;
(define (mix-lock->expressions lockfile package-name)
"Given LOCKFILE, a 'mix.lock' file, import its content as source
expressions. Return a source list and a mix inputs entry for PACKAGE-NAME
referencing all imported sources."
(define (mix-lock-entry->guix-source mix-lock-entry)
(match mix-lock-entry
(('mix-lock-entry
('entry-name entry-name)
('entry-hexpm
('hexpm-name hexpm-name)
('hexpm-version hexpm-version)
_
('hexpm-checksum hexpm-checksum)))
`(define
,(string->symbol
(string-append
(beam-name->package-name entry-name) "-" hexpm-version))
(hexpm-source ,entry-name ,hexpm-name ,hexpm-version
,(bytevector->nix-base32-string
(base16-string->bytevector hexpm-checksum)))))
;; Git snapshot.
(('mix-lock-entry
('entry-name entry-name)
('entry-git
('git-url git-url)
('git-commit git-commit)))
(begin
(let* ((version (string-append "snapshot." (string-take git-commit 7)))
(checksum
(second
(string-split
(with-output-to-string
(lambda _
(guix-download "-g" git-url
(string-append "--commit=" git-commit))))
#\newline))))
`(define
,(string->symbol
(string-append
(beam-name->package-name entry-name) "-" version))
(origin
(method git-fetch)
(uri (git-reference
(url ,git-url)
(commit ,git-commit)))
(file-name
(git-file-name
,(beam-name->package-name entry-name) ,version))
(sha256 (base32 ,checksum)))))))
(else #f)))
(let* ((source-expressions
(filter-map mix-lock-entry->guix-source
(mix-lock-string->scm
(call-with-input-file lockfile get-string-all))))
(beam-inputs-entry
`(,(string->symbol package-name) =>
(list ,@(map second source-expressions)))))
(values source-expressions beam-inputs-entry)))
(define* (mix-inputs-from-lockfile #:optional (lockfile "mix.lock"))
"Given LOCKFILE (default to \"mix.lock\" in current directory), return a
source list imported from it, to be used as package inputs. This procedure
can be used for adding a manifest file within the source tree of a BEAM
application."
(let ((source-expressions
mix-inputs-entry
(mix-lock->expressions lockfile "mix-inputs-temporary")))
(eval-string
(call-with-output-string
(lambda (port)
(for-each
(cut pretty-print-with-comments port <>)
`((use-modules (guix build-system mix))
,@source-expressions
(define-mix-inputs lookup-mix-inputs ,mix-inputs-entry)
(lookup-mix-inputs 'mix-inputs-temporary))))))))
(define (find-mix-inputs-location file)
"Search in FILE for a top-level definition of mix inputs. Return the
location if found, or #f otherwise."
(find-definition-location file 'lookup-mix-inputs
#:define-prefix 'define-mix-inputs))
(define* (extract-mix-inputs file #:key exclude)
"Search in FILE for a top-level definition of mix inputs. If found,
return its entries excluding EXCLUDE, or an empty list otherwise."
(call-with-input-file file
(lambda (port)
(do ((syntax (read-syntax port)
(read-syntax port)))
((match (syntax->datum syntax)
(('define-mix-inputs 'lookup-mix-inputs _ ...) #t)
((? eof-object?) #t)
(_ #f))
(or (and (not (eof-object? syntax))
(match (syntax->datum syntax)
(('define-mix-inputs 'lookup-mix-inputs inputs ...)
(remove (lambda (mix-input-entry)
(eq? exclude (first mix-input-entry)))
inputs))))
'()))))))
+201
View File
@@ -0,0 +1,201 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2025 Igorj Gorjaĉev <igor@goryachev.org>
;;;
;;; This file is part of GNU Guix.
;;;
;;; GNU Guix is free software; you can redistribute it and/or modify it
;;; under the terms of the GNU General Public License as published by
;;; the Free Software Foundation; either version 3 of the License, or (at
;;; your option) any later version.
;;;
;;; GNU Guix is distributed in the hope that it will be useful, but
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;;; GNU General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
(define-module (guix import mix mix-lock)
#:use-module (ice-9 peg)
#:export (mix-lock-string->scm
entry-git
entry-hexpm
entry-name
git-commit
git-url
hexpm-build-system
hexpm-build-systems
hexpm-name
hexpm-version
mix-lock
mix-lock-entry))
;;;
;;; PEG parser for mix.lock.
;;;
(define (mix-lock-string->scm str)
(peg:tree (search-for-pattern mix-lock str)))
;; Auxiliar peg patterns
(define-peg-pattern numeric-char body
(range #\0 #\9))
(define-peg-pattern lowercase-char body
(range #\a #\z))
(define-peg-pattern uppercase-char body
(range #\A #\Z))
(define-peg-pattern alphabetic-char body
(or lowercase-char uppercase-char))
(define-peg-pattern alphanumeric-char body
(or alphabetic-char numeric-char))
(define-peg-pattern space-char body
(+ (or " " "\t" "\n" "\r")))
(define-peg-pattern opt-space-char body
(* space-char))
;; string: "string"
(define-peg-pattern string-char body
(or alphanumeric-char
space-char
"_" "." "~" "=" "<" ">" "/" ":" "-"))
(define-peg-pattern string body
(and (ignore "\"")
(* string-char)
(ignore "\"")))
;; atom: :hex or true | false | nil
(define-peg-pattern atom-char body
(or alphanumeric-char "_" "@" "?" "!"))
(define-peg-pattern atom body
(or
(and (ignore ":")
(+ atom-char))
"true" "false" "nil"))
;; list: [ ... ]
(define-peg-pattern list body
(and (ignore "[")
(* (and
(ignore (? ", "))
(or value key-value)))
(ignore "]")))
;; tuple: { ... }
(define-peg-pattern tuple body
(and (ignore "{")
(* (and
(ignore (? ", "))
value))
(ignore "}")
(ignore (? "\n"))))
;; syntactic sugar for [{key, value} ...]
(define-peg-pattern key-value body
(ignore
(and (+ atom-char) ": " value)))
;; value may be string, atom, tuple, list
(define-peg-pattern value body
(and (ignore opt-space-char)
(or string atom tuple list)
(ignore opt-space-char)))
;; ignore several constructions
(define-peg-pattern ignore-string body
(ignore
(and "\""
(* (or string-char
space-char))
"\"")))
(define-peg-pattern ignore-comma-space body
(ignore ", "))
(define-peg-pattern ignore-list body
(ignore (and "["
(* (and
(? ", ")
(or value key-value)))
"]")))
;; exported symbols
(define-peg-pattern entry-name all
string)
(define-peg-pattern hexpm-name all
atom)
(define-peg-pattern hexpm-version all
string)
(define-peg-pattern hexpm-checksum all
string)
(define-peg-pattern hexpm-build-system all
(capture (+ (or alphanumeric-char "_" "-"))))
(define-peg-pattern hexpm-build-systems all
(and (ignore "[")
(capture
(* (and (ignore ":")
(capture hexpm-build-system)
(ignore (? ", ")))))
(ignore "]")))
(define-peg-pattern git-url all
string)
(define-peg-pattern git-commit all
string)
(define-peg-pattern entry-hexpm all
(and
(ignore ": {:hex, ")
hexpm-name
ignore-comma-space
(capture hexpm-version)
ignore-comma-space
ignore-string
ignore-comma-space
(capture hexpm-build-systems)
ignore-comma-space
ignore-list
ignore-comma-space
ignore-string
ignore-comma-space
(capture hexpm-checksum)
(ignore "}")))
(define-peg-pattern entry-git all
(and
(ignore ": {:git, ")
git-url
ignore-comma-space
git-commit
ignore-comma-space
ignore-list
(ignore "}")))
(define-peg-pattern mix-lock-entry all
(and (ignore (? " "))
(capture entry-name)
(or
entry-hexpm
entry-git)
(ignore (? ",\n"))))
;; mix.lock
(define-peg-pattern mix-lock all
(and (ignore "%{\n")
(* mix-lock-entry)
(ignore "}")))
+11 -9
View File
@@ -7,6 +7,7 @@
;;; Copyright © 2021 Xinglu Chen <public@yoctocell.xyz> ;;; Copyright © 2021 Xinglu Chen <public@yoctocell.xyz>
;;; Copyright © 2022 Philip McGrath <philip@philipmcgrath.com> ;;; Copyright © 2022 Philip McGrath <philip@philipmcgrath.com>
;;; Copyright © 2024 Herman Rimm <herman@rimm.ee> ;;; Copyright © 2024 Herman Rimm <herman@rimm.ee>
;;; Copyright © 2025 Igorj Gorjaĉev <igor@goryachev.org>
;;; ;;;
;;; This file is part of GNU Guix. ;;; This file is part of GNU Guix.
;;; ;;;
@@ -63,6 +64,7 @@
(define importers '("composer" "cpan" "cran" "crate" "egg" "elm" "elpa" (define importers '("composer" "cpan" "cran" "crate" "egg" "elm" "elpa"
"gem" "gnu" "go" "hackage" "hexpm" "json" "luanti" "gem" "gnu" "go" "hackage" "hexpm" "json" "luanti"
"minetest" ; deprecated "minetest" ; deprecated
"mix"
"npm-binary" "nuget" "opam" "pypi" "stackage" "texlive")) "npm-binary" "nuget" "opam" "pypi" "stackage" "texlive"))
(define (resolve-importer name) (define (resolve-importer name)
@@ -143,10 +145,10 @@ PROC callback."
((or ("-i" file importer args ...) ((or ("-i" file importer args ...)
("--insert" file importer args ...)) ("--insert" file importer args ...))
(let* ((define-prefixes (let* ((define-prefixes
`(,@(if (member importer '("crate")) `(,@(if (member importer '("crate" "mix"))
'(define) '(define)
'()) '())
define-public)) define-public))
(define-prefix? (cut member <> define-prefixes)) (define-prefix? (cut member <> define-prefixes))
(find-and-insert (find-and-insert
(lambda (expr) (lambda (expr)
@@ -172,9 +174,9 @@ PROC callback."
((importer args ...) ((importer args ...)
(let ((print (lambda (expr) (let ((print (lambda (expr)
(leave-on-EPIPE (leave-on-EPIPE
(pretty-print-with-comments (pretty-print-with-comments
(current-output-port) expr) (current-output-port) expr)
;; Two newlines: one after the closing paren, and ;; Two newlines: one after the closing paren, and
;; one to leave a blank line. ;; one to leave a blank line.
(newline) (newline))))) (newline) (newline)))))
(import-as-definitions importer args print))))) (import-as-definitions importer args print)))))
+8 -1
View File
@@ -47,6 +47,8 @@ Import and convert the hex.pm package for PACKAGE-NAME.\n"))
(newline) (newline)
(display (G_ " (display (G_ "
-r, --recursive import packages recursively")) -r, --recursive import packages recursively"))
(display (G_ "
-m, --mix-inputs use mix-inputs for input field"))
(newline) (newline)
(show-bug-report-information)) (show-bug-report-information))
@@ -62,6 +64,9 @@ Import and convert the hex.pm package for PACKAGE-NAME.\n"))
(option '(#\r "recursive") #f #f (option '(#\r "recursive") #f #f
(lambda (opt name arg result) (lambda (opt name arg result)
(alist-cons 'recursive #t result))) (alist-cons 'recursive #t result)))
(option '("mix-inputs") #f #f
(lambda (opt name arg result)
(alist-cons 'mix-inputs #t result)))
%standard-import-options)) %standard-import-options))
@@ -94,7 +99,9 @@ Import and convert the hex.pm package for PACKAGE-NAME.\n"))
(_ #f)) (_ #f))
(hexpm-recursive-import name version)) (hexpm-recursive-import name version))
;; Single import ;; Single import
(let ((sexp (hexpm->guix-package name #:version version))) (let* ((mix-inputs (assoc-ref opts 'mix-inputs))
(sexp (hexpm->guix-package name #:version version
#:mix-inputs? mix-inputs)))
(unless sexp (unless sexp
(leave (G_ "failed to download meta-data for package '~a'~%") (leave (G_ "failed to download meta-data for package '~a'~%")
spec)) spec))
+122
View File
@@ -0,0 +1,122 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2025 Igorj Gorjaĉev <igor@goryachev.org>
;;;
;;; This file is part of GNU Guix.
;;;
;;; GNU Guix is free software; you can redistribute it and/or modify it
;;; under the terms of the GNU General Public License as published by
;;; the Free Software Foundation; either version 3 of the License, or (at
;;; your option) any later version.
;;;
;;; GNU Guix is distributed in the hope that it will be useful, but
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;;; GNU General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
(define-module (guix scripts import mix)
#:use-module (guix ui)
#:use-module (guix utils)
#:use-module (guix read-print)
#:use-module (guix scripts)
#:use-module (guix import mix)
#:use-module (guix scripts import)
#:use-module (srfi srfi-1)
#:use-module (srfi srfi-37)
#:use-module (srfi srfi-71)
#:use-module (ice-9 match)
#:export (guix-import-mix))
;;;
;;; Command-line options.
;;;
(define %default-options
'())
(define (show-help)
(display (G_ "Usage: guix import mix PACKAGE-NAME
Import package dependencies from its 'mix.lock'.\n"))
(display (G_ "
-h, --help display this help and exit"))
(display (G_ "
-V, --version display version information and exit"))
(newline)
(display (G_ "
-f, --lockfile=FILE import dependencies from FILE, a 'mix.lock' file"))
(newline)
(show-bug-report-information))
(define %options
;; Specification of the command-line options.
(cons* (option '(#\h "help") #f #f
(lambda args
(show-help)
(exit 0)))
(option '(#\V "version") #f #f
(lambda args
(show-version-and-exit "guix import mix")))
(option '(#\f "lockfile") #f #t
(lambda (opt name arg result)
(if (file-exists? arg)
(alist-cons 'lockfile arg result)
(leave (G_ "file '~a' does not exist~%") arg))))
%standard-import-options))
;;;
;;; Entry point.
;;;
(define (guix-import-mix . args)
(define (parse-options)
;; Return the alist of option values.
(parse-command-line args %options (list %default-options)
#:build-options? #f))
(let* ((opts (parse-options))
(lockfile (assoc-ref opts 'lockfile))
(file-to-insert (assoc-ref opts 'file-to-insert))
(args (filter-map (match-lambda
(('argument . value)
value)
(_ #f))
(reverse opts))))
(match args
((spec)
(define-values (name version)
(package-name->name+version spec))
(if lockfile
(let ((source-expressions
_
(mix-lock->expressions lockfile name)))
(when file-to-insert
(let* ((source-expressions
mix-inputs-entry
(mix-lock->expressions lockfile name))
(term (first mix-inputs-entry))
(mix-inputs
`(define-mix-inputs lookup-mix-inputs
,@(sort
(cons mix-inputs-entry
(extract-mix-inputs
file-to-insert #:exclude term))
(lambda (a b)
(string< (symbol->string (first a))
(symbol->string (first b)))))))
(_
(and=> (find-mix-inputs-location file-to-insert)
delete-expression))
(port (open-file file-to-insert "a")))
(pretty-print-with-comments port mix-inputs)
(newline port)
(close-port port)))
source-expressions)))
(()
(leave (G_ "too few arguments~%")))
((many ...)
(leave (G_ "too many arguments~%"))))))
+44
View File
@@ -250,4 +250,48 @@
(x (x
(pk 'fail x #f)))))) (pk 'fail x #f))))))
(test-assert "hexpm-with-mix-inputs"
;; Replace network resources with sample data.
(mock ((guix http-client) http-fetch
(lambda (url . rest)
(match url
("https://hex.pm/api/packages/bla"
(values (open-input-string test-bla-package)
(string-length test-bla-package)))
("https://hex.pm/api/packages/bla/releases/1.5.0"
(values (open-input-string test-bla-release)
(string-length test-bla-release)))
(_ (error "http-fetch got unexpected URL: " url)))))
(mock ((guix build download) url-fetch
(lambda* (url file-name
#:key
(mirrors '()) verify-certificate?)
(with-output-to-file file-name
(lambda ()
(display
(match url
("https://repo.hex.pm/tarballs/bla-1.5.0.tar"
"source")
(_ (error "url-fetch got unexpected URL: " url))))))))
(match (hexpm->guix-package "bla" #:mix-inputs? #t)
(`(package
(name "erlang-bla")
(version "1.5.0")
(source
(origin
(method url-fetch)
(uri (hexpm-uri "bla" version))
(sha256
(base32
"0zcl4dgcmqwl1g5xb901pd6dz61r1xgmac9mqlwvh022paa6gks1"))))
(build-system rebar-build-system)
(inputs (mix-inputs 'erlang-bla))
(synopsis "A cool package")
(description "This package provides a cool package.")
(home-page "https://hex.pm/packages/bla")
(license (list license:expat license:asl2.0)))
#t)
(x
(pk 'fail x #f))))))
(test-end "hexpm") (test-end "hexpm")
+97
View File
@@ -0,0 +1,97 @@
;;; GNU Guix --- Functional package management for GNU
;;; Copyright © 2025 Igorj Gorjaĉev <igor@goryachev.org>
;;;
;;; This file is part of GNU Guix.
;;;
;;; GNU Guix is free software; you can redistribute it and/or modify it
;;; under the terms of the GNU General Public License as published by
;;; the Free Software Foundation; either version 3 of the License, or (at
;;; your option) any later version.
;;;
;;; GNU Guix is distributed in the hope that it will be useful, but
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;;; GNU General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>.
(define-module (test-mix)
#:use-module (guix import mix)
#:use-module (guix base32)
#:use-module (guix build-system mix)
#:use-module (gcrypt hash)
#:use-module (guix tests)
#:use-module (srfi srfi-11)
#:use-module (srfi srfi-64)
#:use-module (ice-9 binary-ports)
#:use-module (ice-9 match))
(define test-mix-lock-file
"\
%{
\"gen_stage\": {:hex, :gen_stage, \"1.3.2\", \
\"7c77e5d1e97de2c6c2f78f306f463bca64bf2f4c3cdd606affc0100b89743b7b\", \
[:mix], [], \"hexpm\", \
\"0ffae547fa777b3ed889a6b9e1e64566217413d018cabd825f786e843ffe63e7\"},
\"eini\": {:hex, :eini_beam, \"2.2.4\", \
\"02143b1dce4dda4243248e7d9b3d8274b8d9f5a666445e3d868e2cce79e4ff22\", \
[:rebar3], [], \"hexpm\", \
\"12de479d144b19e09bb92ba202a7ea716739929afdf9dff01ad802e2b1508471\"},
\"erlydtl\": {:git, \"https://github.com/manuel-rubio/erlydtl.git\", \
\"dffa1a73ee2bfba14195b8b3964c39f007ff1284\", []},
}")
(define temp-file
(string-append "t-mix-" (number->string (getpid))))
(test-begin "mix")
(test-assert "mix-lock-file-import"
(begin
(call-with-output-file temp-file
(lambda (port)
(display test-mix-lock-file port)))
(mock
((guix scripts download) guix-download
(lambda _
(format #t "~a~%~a~%"
"/gnu/store/m43vixiijc26ni5p9zvbvjrs311h4fsm-erlydtl-dffa1a7"
"1jhcfh0idadlh9999kjzx1riqjw0k05wm6ii08xkjvirhjg0vawh")))
(let-values
(((source-expressions beam-inputs-entry)
(mix-lock->expressions temp-file "test")))
(and
(match source-expressions
('((define beam-gen-stage-1.3.2
(hexpm-source
"gen_stage" "gen_stage" "1.3.2"
"1rv3zqzq8vkqby1bvjhqs09p88b68pkf3fd6i7c3wyvpz93ybyhg"))
(define beam-eini-2.2.4
(hexpm-source
"eini" "eini_beam" "2.2.4"
"0wc4a2qy40nq3bqdzygxka93jrvixakh58ibp6dy06ab2jflgphj"))
(define beam-erlydtl-snapshot.dffa1a7
(origin
(method git-fetch)
(uri (git-reference
(url "https://github.com/manuel-rubio/erlydtl.git")
(commit "dffa1a73ee2bfba14195b8b3964c39f007ff1284")))
(file-name (git-file-name "beam-erlydtl" "snapshot.dffa1a7"))
(sha256
(base32
"1jhcfh0idadlh9999kjzx1riqjw0k05wm6ii08xkjvirhjg0vawh")))))
#t)
(x
(pk 'fail (pretty-print-with-comments (current-output-port) x) #f)))
(match beam-inputs-entry
(`(test => (list beam-gen-stage-1.3.2
beam-eini-2.2.4
beam-erlydtl-snapshot.dffa1a7))
#t)
(x
(pk 'fail x #f))))))))
(test-end "mix")
(false-if-exception (delete-file temp-file))