首页 文章

nix路径类型何时进入nix存储区,何时不进入?

提问于
浏览
6

我在过去注意到在 nix 中,似乎是 ./myfile.txt 路径类型

  • 有时评估为 /home/myuser/mydir/myfile.txt ,和

  • 有时候 /nix/store/55j24v9qwdarikv7kd3lc0pvxdr9r2y8-myfile.txt .

我想知道究竟何时发生这种情况 .

这对于包含任何形式的秘密信息的文件尤其重要,因为 /nix/store 中的所有文件都是系统上所有用户都可以读取的 .

(当使用 nixops 时,为此目的有一个特殊的"keys"功能,请参阅本手册中的Managing keys部分,但我认为在 nix 本身发生这种路径到存储路径复制的时间和方式仍然很重要 . )

1 回答

  • 11

    #nixos IRC Channels 上的用户 clever 解释说:

    当它发生时

    扩展到 /nix/store/... 发生 when you use a path inside ${} string interpolation ,例如 mystring = "cat ${./myfile.txt} .

    It does not happen when you use the toString function ,例如 toString ./myfile.txt 不会给你指向 /nix/store 的路径 .

    例如:

    toString ./notes.txt == "/home/clever/apps/nixos-installer/installer-gui/notes.txt"
    "${./notes.txt}"     == "/nix/store/55j24v9qwdarikv7kd3lc0pvxdr9r2y8-notes.txt"
    

    怎么回事

    55j24v9qwdarikv7kd3lc0pvxdr9r2y8 哈希部分取自 ./path 引用的文件的内容,以便在文件更改时更改,并且依赖于它的内容可以相应地重建 .

    将文件复制到 /nix/store 时发生在 nix-instantiate ; nix表达式的评估仍然是纯粹的功能(在评估时不会发生复制),但实例化("building")则不然 .

    为了实现这一点, nix 中的每个字符串都有一个"context"来跟踪字符串所依赖的内容(实际上是它背后的 .drv 路径列表) .

    例如, GNU hello 包中的字符串 "/nix/store/rkvwvi007k7w8lp4cc0n10yhlz5xjfmk-hello-2.10" 具有一些不可见状态,表示它取决于 hello 派生 . 如果该字符串作为stdenv.mkDerivation的输入结束,则新建的派生将依赖于正在构建的 hello 包 .

    即使你通过 builtins.substring 搞乱字符串,这也有效 . 请参阅nix的this code,了解如何在第1653行中提取较长字符串的上下文,并将其用作第1657行中子字符串的上下文 .

    您可以使用 builtins.unsafeDiscardStringContext 删除字符串的依赖关系上下文 .

    在nix代码中发生的地方

    ${} interpolation使用coerceToString,其 bool copyToStore 参数默认为 true

    /* String coercion.  Converts strings, paths and derivations to a
       string.  If `coerceMore' is set, also converts nulls, integers,
       booleans and lists to a string.  If `copyToStore' is set,
       referenced paths are copied to the Nix store as a side effect. */
    string coerceToString(const Pos & pos, Value & v, PathSet & context,
                          bool coerceMore = false, bool copyToStore = true);
    

    它被实现here,并且检查插值的东西是 ./path ,并且复制到 /nix/store ,正在发生just below

    if (v.type == tPath) {
        Path path(canonPath(v.path));
        return copyToStore ? copyPathToStore(context, path) : path;
    }
    

    toStringprim_toString实现,它为 copyToStore 参数传递 false

    /* Convert the argument to a string.  Paths are *not* copied to the
       store, so `toString /foo/bar' yields `"/foo/bar"', not
       `"/nix/store/whatever..."'. */
    static void prim_toString(EvalState & state, const Pos & pos, Value * * args, Value & v)
    {
        PathSet context;
        string s = state.coerceToString(pos, *args[0], context, true, false);
        mkString(v, s, context);
    }
    

相关问题