在GUIX中,如何使用旧版本的软件包,不再在频道中?

在GUIX中,如何使用旧版本的软件包,不再在频道中?

GUIX 吸引我的部分原因是可以同时“安装”各种不同版本的软件包,而不会相互干扰。但我不知道如何实际使用这些不同的版本。

比如最近,pyyaml软件包已从 5.4.1 升级到 6.0。由于种种原因,我想继续使用5.4.1。 (我只是在这里使用 pyyaml 作为示例。)我的商店里确实有旧版本:

$ ls -d1 /gnu/store/*pyyaml*
/gnu/store/22v8l25b33vs65wjd9ap28n772bvlih3-python-pyyaml-5.4.1/
/gnu/store/2j2s1jd6y8x7mlqjp968955misx1qw1c-python-pyyaml-6.0/
/gnu/store/54imz4x65s3xbjrgrfswgk815gfkhk4b-python-pyyaml-5.4.1/
/gnu/store/6537a8na1rbilffqqi642q0lipqfi2zg-python-pyyaml-5.4.1.drv
/gnu/store/6flrrmhq203vg6awdw7r2lsmzix4g2rh-python-pyyaml-6.0-guile-builder
/gnu/store/73k3qdz9rdh64pl7a0f0951zm2pbx5s2-python-pyyaml-5.4.1.drv
/gnu/store/7bcbwi93ihz8v2sdzmj6l9vhjqaxr14l-python-pyyaml-5.4.1-builder
...

我如何使用这些旧版本?

仅单独使用这样的旧版本就可以了。例如,我希望这样的事情能够起作用:

$ guix shell "[email protected]" python
guix shell: error: python-pyyaml: package not found for version 5.4.1

此错误是预料之中的,因为旧版本在我的频道中不可用。因此,也许可以以某种方式指定要使用的旧版本通道,但我不知道如何指定。


关于 XY 问题的侧节点,这个问题的直接原因是 docker-compose 现在不再工作:

$ guix shell docker-compose
guix shell: error: build of `/gnu/store/8qhvnw5mwra9i6ji24xlywcpdl0rdznn-docker-compose-1.29.2.drv' failed
$ zcat /var/log/guix/drvs/8q/hvnw5mwra9i6ji24xlywcpdl0rdznn-docker-compose-1.29.2.drv.gz
...checking requirements: ERROR: docker-compose==1.29.2 ContextualVersionConflict(PyYAML 6.0 (/gnu/store/igfl4023dzvl8vi6xs1m96lcsr4fdw07-python-pyyaml-6.0/lib/python3.9/site-packages), Requirement.parse('PyYAML<6,>=3.10'), {'docker-compose'})

但是,我并不特别关心 docker-compose (关于这个问题)。如果有的话,这个问题是我用 GUIX 原生工具取代它的旅程的一部分。

(另外,我知道 pyyaml 6 对其用户强制使用一些安全功能,因此不应再使用 pyyaml 5;pyyaml 仅用作示例。)

答案1

第三次是魅力,使用下等人的清单似乎是最好的。

info guix Inferiors详情请参阅。这是信息页面的快照。 (有趣的是,他们的用例与我的非常相似:使用旧版本的 json 库作为 guile 解释器,而不是使用旧版本的 yaml 库作为 python 解释器。)

     Note: The functionality described here is a “technology preview” as
     of version 0.0-git.  As such, the interface is subject to change.

   Sometimes you might need to mix packages from the revision of Guix
you’re currently running with packages available in a different revision
of Guix.  Guix “inferiors” allow you to achieve that by composing
different Guix revisions in arbitrary ways.

   ...

   When combined with channels (*note Channels::), inferiors provide a
simple way to interact with a separate revision of Guix.  For example,
let’s assume you want to install in your profile the current ‘guile’
package, along with the ‘guile-json’ as it existed in an older revision
of Guix—perhaps because the newer ‘guile-json’ has an incompatible API
and you want to run your code against the old API.  To do that, you
could write a manifest for use by ‘guix package --manifest’ (*note
Invoking guix package::); in that manifest, you would create an inferior
for that old Guix revision you care about, and you would look up the
‘guile-json’ package in the inferior.

继续举一个例子。以下是适用于该特定用例的相同示例:

$ cat mypyyamlmanifest.scm
(use-modules (guix inferior) (guix channels)
             (srfi srfi-1))

(define channels
  (list (channel
         (name 'guix)
         (url "https://git.savannah.gnu.org/git/guix.git")
         (commit
          ;; The commit with the python-pyyaml 5.4.1
          "d3e1a94391a838332b0565d56762a58cf87ac6b1"))))

(define inferior
  (inferior-for-channels channels))

(packages->manifest
 (list (first (lookup-inferior-packages inferior "python-pyyaml"))
       (specification->package "python")))

$ guix shell -m mypyyamlmanifest.scm 
...

$ python3 -c "import yaml; print(yaml.__version__)"
5.4.1

反思为什么花了这么长时间才找到这些信息。 (也许 GUIX 开发人员会读到这篇文章,也许我可以用它来为文档提供补丁。)

guix info guix package是我使用清单的起点。描述--manifest中有关于如何制作清单的简短示例,但没有讨论渠道。有一个指向--export-manifest描述的链接,我通过该链接了解如何重新创建为创建的环境我的第一个答案。该部分解释说此导出不包含通道信息,这使我得出结论,清单根本不包含通道信息并且需要第二个文件(我的第二个答案)。描述--export-manifest链接到--export-channels其正下方,起初我没有阅读,因为我只是调整了现有的channels.scm.然而,该部分最后解释了需要下等人。

--manifest如果的部分guix package解释可以直接在清单中定义通道,我可能会更容易理解。

如果我理解正确的话,劣等在技术上与通道不同,所以上面的最后一句话是错误的,并且不可能在清单中定义通道。然而在实践中,似乎可以对清单中的所有包使用次等包,从而有效地对清单中的通道进行硬编码。这让我想知道直接在清单中允许通道规范是否会更简单。


在回答问题时,这个解决方案仍然不足以解决触发问题的最初问题: running docker-compose,因为docker-compose仍然使用python-pyyaml原始通道中的 。有可能让一个包使用次等作为输入使用modify-inputs。这使得可以只docker-compose使用python-pyyaml劣质的过时的,而让配置文件的其余部分使用python-pyyaml原始渠道的较新的。

答案2

感谢优秀的info guix页面,我认为这是可行的:

guix shell \
    --with-git-url=python-pyyaml="https://github.com/yaml/pyyaml.git" \
    --with-branch=python-pyyaml="release/5.4.1" \
    python-pyyaml python

但如果已经有一个完美的包定义,感觉有点hackishhttps://git.savannah.gnu.org/cgit/guix.git/tree/gnu/packages/python-xyz.scm?h=d3e1a94391a838332b0565d56762a58cf87ac6b1#n3907

pyyaml一个非常简单的包,很好地托管在 github 上,遵循标准 git 分支和 Python 安装程序。但某些包可能更复杂,这样简单的替换可能不起作用。

有没有某种方法可以指定通道 git url 上的特定提交以用于包? (或者完整的guix shell命令?)


编辑:这个解决方案不是很好的另一个原因是它不适用于--export-manifest

$ guix shell \
    --with-git-url=python-pyyaml="https://github.com/yaml/pyyaml.git" \
    --with-branch=python-pyyaml="release/5.4.1" \
    --export-manifest \
    python-pyyaml python > mymanifest.scm

$ guix shell -m mymanifest.scm
guix shell: error: the source of [email protected] is not a Git 

mymanifest.scm

$ cat mymanifest.scm
;; What follows is a "manifest" equivalent to the command line you gave.
;; You can store it in a file that you may then pass to any 'guix' command
;; that accepts a '--manifest' (or '-m') option.

(use-modules (guix transformations))

(define transform1
  (options->transformation
    '((with-git-url
        .
        "python-pyyaml=https://github.com/yaml/pyyaml.git")
      (with-branch . "python-pyyaml=release/5.4.1"))))

(packages->manifest
  (list (transform1
          (specification->package "python-pyyaml"))
        (transform1 (specification->package "python"))))

答案3

这也许更加 GUIXy:

  • 从仍具有 pyyaml 5.4.1 的提交创建通道文件。
  • 从该通道文件创建配置文件。
  • 激活该配置文件。
  • 使用所需的包创建清单。
  • 使用该清单创建一个 shell。
$ cat mypyyamlchannels.scm
(list (channel
        (name 'guix)
        (url "https://git.savannah.gnu.org/git/guix.git")
        (branch "master")
        (commit
          "d3e1a94391a838332b0565d56762a58cf87ac6b1")
        (introduction
          (make-channel-introduction
            "9edb3f66fd807b096b48283debdcddccfea34bad"
            (openpgp-fingerprint
              "BBB0 2DDF 2CEA F6A8 0D1D  E643 A2A0 6DF2 A33A 54FA")))))

$ guix pull -C mypyyamlchannels.scm -p mypyyamlprofile

$ GUIX_PROFILE="$(realpath mypyyamlprofile)"

$ . "$GUIX_PROFILE/etc/profile"

$ guix shell python-pyyaml python --export-manifest > mypyyamlmanifest.scm

$ cat mypyyamlmanifest.scm 
;; What follows is a "manifest" equivalent to the command line you gave.
;; You can store it in a file that you may then pass to any 'guix' command
;; that accepts a '--manifest' (or '-m') option.

(specifications->manifest
  (list "python-pyyaml" "python"))

$ guix shell -m mypyyamlmanifest.scm

但这有两个缺点:

  • 这有点冗长。它需要 2 个文件(通道和清单)和 4 个命令(guix pull、set GUIX_PROFILE、源配置文件、guix shell)和 2 个符号链接 ( mypyyamlprofile, mypyyamlprofile-1-link) 来重新创建相同的环境。不起作用的转换解决方案只需要 1 个清单文件和 1 个 guix shell 命令。是否有一种方法可以将通道和清单文件组合成一个东西,然后可以用来在单个命令中实例化 shell?
  • 它不允许从主通道进行混合和匹配。我认为混合需要创建一个组合默认通道的通道文件,然后以某种方式从具有特定提交的通道中挑选 python-pyyaml 包。这可能会导致不一致,但这些可能是可以解决的。

编辑:显然劣质会让混合和匹配更容易:

   Sometimes you might need to mix packages from the revision of Guix
you’re currently running with packages available in a different revision
of Guix.  Guix “inferiors” allow you to achieve that by composing
different Guix revisions in arbitrary ways.

相关内容