fetchFromGitHub,过滤并用作 environment.etc."file".source

fetchFromGitHub, filter down and use as environment.etc."file".source

我在从 github 下载文件时遇到了一些问题,我想知道是否有人可以帮我把它下载下来并将其作为我的 /etc 中的文本(或源)文件夹。理想情况下,我正在尝试执行以下操作(但使用 .text):

environment.etc."sb_hosts".source = (builtins.filterSource
  (path: type: path == "hosts" && type == "regular")
  (fetchFromGitHub {
    owner = "StevenBlack";
    repo = "hosts";
    rev = "v2.1.19";
    sha256 = "1wrwlgcy46vwji0n1imnmlci03ln0v4qd27cw8cwpag57w06n4z7";
  }));

但是我收到一个错误,结果是:

string '/nix/store/r3xnh6ricqa7lnnbb0ka5vb0h6rw28ap-source' cannot refer to other paths, at /etc/nixos/configuration.nix:13:38

为了进行比较,我可以 运行 fetchFromGitHub 直接使用 .source,这将按预期将 git 存储库下拉到 /etc/sb_hosts/

到目前为止,我已尝试使用 builtins.filterSource,如 Nix manual: 15.5. Builtin functions, and I've also tried to use cleanSourceWith 中所述——主要是因为我找不到 builtins.filterSource 的来源。即使我访问 lib.cleanSourceWith.outPath (回想起来,这只是调用 filterSource),这两个都会产生相同的错误。


如果这不可能,做这样的事情的推荐路线是什么?最终输出是我想从网络上收集已知的、版本化的广告块主机文件,然后将它们与我自己的本地主机文件合并。

编辑:发帖后我意识到 raw.githubusercontent.com 服从标记版本;使用 fetchurl 这将回答我原来的问题。现在我只是想知道为什么上面的代码块不起作用以及我将如何实现相同的效果。

您可以使用 path+string-串联得到单个 file/subdirectory。

environment.etc."sb_hosts".source =
  fetchFromGitHub {
    owner = "StevenBlack";
    repo = "hosts";
    rev = "v2.1.19";
    sha256 = "1wrwlgcy46vwji0n1imnmlci03ln0v4qd27cw8cwpag57w06n4z7";
  } + "/hosts";

为什么这样做?

您可以将路径与字符串连接起来以引用子路径(它也将是 path)。派生(例如 fetchFromGitHub args)隐含地强制转换为它们将在构建后生成的路径。

为什么问题中提出的解决方案不起作用?

builtins.filterSource(及其同级 lib.cleanSource{,With})将在删除所有未通过谓词的文件后将 path 复制到存储中。值得注意的是,存储副本(和相应的缓存)发生在应用谓词之后。

这主要用于与它们打包的源代码内联的 Nix 定义,以避免在无关文件(例如 __pycache__.git 文件夹)更改时导致重建。

这对于派生没有多大意义,因为它们 已经 在 Nix 商店中,并且由它们的构建输入而不是输出来识别。

错误信息是什么意思?

/nix/store/r3xnh6ricqa7lnnbb0ka5vb0h6rw28ap-source 是推导的输出,所以 Nix 强制它存在(或被构建),然后才能依次构建使用它的任何东西。为什么他们选择称这种关系为 refers 远远超出我的理解。

解决实际问题

您可以使用 networking.extraHosts option. This property expects the contents directly as a string, but that can be solved using builtins.readFile.

添加额外条目到您的 /etc/hosts

因此:

networking.extraHosts = builtins.readFile
  (fetchFromGitHub {
    owner = "StevenBlack";
    repo = "hosts";
    rev = "v2.1.19";
    sha256 = "1wrwlgcy46vwji0n1imnmlci03ln0v4qd27cw8cwpag57w06n4z7";
  } + "/hosts");