如何将 `import <nixpkgs> {}` 调用固定到特定提交? 方法 0方法一

问题描述

在尝试恢复旧项目时,有时我必须四处寻找旧的 Nixpkgs 提交才能开始工作。

例如,我的大部分 shell.nix 文件都是这样开头的,

{pkgs ? import <nixpkgs> {} }:

pkgs.mkShell {
  # ...
}

这将从当前 channel 指向的提交中导入所有表达式,但是一段时间后,发生了太多更改,我的项目将不再构建;那么我将不得不找到一个仍然有效的提交,然后从那里开始。

$ nix-shell --arg pkgs \
> 'import (fetchTarball "https://github.com/NixOS/nixpkgs/archive/0c0fe6d85b92c4e992e314bd6f9943413af9a309.tar.gz") {}'

如果我当时能从频道中保存工作提交,并且在以后需要时可以回退到一些可靠的东西,那可能是最好的。

解决方法

>= nixos 20.09

nix-shell -p nix-info --run "nix-info -m"
  • 系统:"x86_64-linux"
  • 主机操作系统:Linux 5.9.15,NixOS,20.09.2344.a3a3dda3bac (Nightingale) # channel-commit
  • 多用户?:yes
  • 沙盒:yes
  • 版本:nix-env (Nix) 2.3.9
  • channels(root): "nixos-20.09.2344.a3a3dda3bac" # channel-commit
  • 频道(用户):"nixos-20.09.2152.e34208e1003" # 频道提交
  • nixpkgs:/nix/var/nix/profiles/per-user/root/channels/nixos

检查结尾,例如a3a3dda3bacNixOS history 中,例如 release 20.09


我不会将 pkgs ? import <nixpkgs> {} 用于开发与您正在运行的当前系统无关的环境

  • 改为导入,例如在 let 区域通过变量

用于开发环境:

# nix-shell shell_test.nix --argstr commitNixpkgs "0c0fe6d85b92c4e992e314bd6f9943413af9a309 --show-trace

{pkgs ? import <nixpkgs> {},commitNixpkgs ? "0c0fe6d85b92c4e992e314bd6f9943413af9a309" ; ref ? "refs/heads/nixpkgs-unstable",rev ? "502845c3e31ef3de0e424f3fcb09217df2ce6df6",...}:

let 
    nixPkgs = import (fetchTarball "https://github.com/NixOS/nixpkgs/archive/${commitNixpkgs}.tar.gz") {config= { allowUnfree = true ; } ;} ; 
    # https://channels.nix.gsc.io/
    # git ls-remote https://github.com/nixos/nixpkgs | grep unstable
 
    # or via fetchGit 
    nixPkgs_fG = import (builtins.fetchGit {
       name = "nixpkgs-unstable";
       url = "https://github.com/nixos/nixpkgs-channels.git";
       ref = ${ref};        #"refs/heads/nixpkgs-unstable";
       rev = ${rev};        #"502845c3e31ef3de0e424f3fcb09217df2ce6df6"; 
   }) {config= { allowUnfree = true ; } ;  } ;
   # nix-shell -p nix-prefetch-git --run ' nix-prefetch-git https://github.com/nixos/nixpkgs.git refs/heads/nixos-unstable '

in 
  ...    
,

要扩展 NixOS 讨论主题 How to see what commit is my channel on? 中提供的答案:

注意在尝试任何这些方法之前,请确保您向正确的用户发出命令!
无论哪种方式都不会造成伤害,但是如果您使用 NixOS 和 manage things declaratively(在重建系统时作为 root),那么您可能会得到与您需要的不同的提交哈希。 (特别是如果您曾经在没有 nix-channel --update 的情况下发布过 sudo,这也会为您的 用户个人资料设置一个频道。)

方法 0

根据 NixOS wiki's Nix channels entry,“a channelNixpkgs 中最新“经过验证的”git 提交的名称。也就是说,在任何给定时间,通道指向 the Nixpkgs git repository on Github 中的特定提交; 每个 Nix 频道实际上是 repo 中的一个 git 分支

$ nix-channel --list
nixos https://nixos.org/channels/nixos-20.09
-----                            ----------- 
(name)                          (branch-name)
#                                     |
#                                     V
#              https://github.com/NixOS/nixpkgs/tree/<branch-name>
#         i.e. https://github.com/NixOS/nixpkgs/tree/nixos-20.09

因此,如果您只是在 nix-channel --update 之前执行了 nix-shell,并且它有效,只需在 Nixpkgs repo 的通道分支中查找最后一次提交。

方法一

"Chapter 12. Channels" of the Nix manual 提到 nix-channel --update "默认情况下使每个通道的 Nix 表达式的联合可用于 nix-env 操作(通过符号链接 ~/.nix-defexpr/channels”。

要查看 ~/.nix-defexpr/channels 符号链接指向的位置,请使用 readlink -f 跟随符号链接链并将其与 ls 结合以直奔主题:

$ ls -l $(readlink -f ~/.nix-defexpr/channels)
total 6432
dr-xr-xr-x    2 root root      4096 Jan  1  1970 ./
drwxrwxr-t 8191 root nixbld 6569984 Feb  9 15:51 ../
lrwxrwxrwx    1 root root        78 Jan  1  1970 nixos -> /nix/store/k737c631q19n54fhjmnf68frg5dar14w-nixos-20.09.3009.8e78c2cfbae/nixos/
lrwxrwxrwx    1 root root        60 Jan  1  1970 manifest.nix -> /nix/store/a5wl1fri2sasnsb1i5zscni5h7kjg7d6-env-manifest.nix

我的频道名称是 nixos,它指向

/nix/store/k7..4w-nixos-20.09.3009.8e78c2cfbae/nixos/
                                   -----------
                                        ^
                                        |
                                   channel-commit

并且提交哈希就在 MAJOR.MINOR.PATCH version number 之后。


旁白:要为问题中的 fetchTarball 构建 tarball URL,请使用以下模板:

https://github.com/<user>/<repo>/archive/<full-or-abbr-commit-hash>.tar.gz

例如:

https://github.com/NixOS/nixpkgs/archive/8e78c2cfbae.tar.gz

或者,单击绿色的“代码”按钮,然后复制“下载 ZIP”链接的 URL(并将 zip 扩展名更改为 tar.gz)。


有趣的事实:如果您在方法 1 之前执行了 nix-channel --update,那么 URL https://github.com/NixOS/nixpkgs/tree/<branch-name>https://github.com/NixOS/nixpkgs/tree/<channel-commit> 将指向 {{3} } 回购。