【问题标题】:When does a nix path type make it into the nix store and when not?nix 路径类型何时进入 nix 存储,何时不进入?
【发布时间】:2017-10-06 14:48:20
【问题描述】:

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

  • 有时评估为/home/myuser/mydir/myfile.txt,并且
  • 有时发送至/nix/store/55j24v9qwdarikv7kd3lc0pvxdr9r2y8-myfile.txt

我想确切地了解哪种情况发生的时间。

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

(当使用nixops 时,有一个特殊的“键”功能用于此目的,请参阅手册中的Managing keys 部分,但我认为路径到存储路径复制何时以及如何发生仍然很重要nix 本身。)

【问题讨论】:

标签: nix nixos


【解决方案1】:

#nixos IRC 频道上的用户 clever 解释:

什么时候发生

扩展到/nix/store/... 发生当您在${} 字符串插值中使用路径时,例如mystring = "cat ${./myfile.txt}

使用toString函数时不会发生,例如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 表达式的 求值 仍然是纯函数式的(在求值时不会发生复制),但 实例化(“构建”)不是。

为了实现这一点,nix 中的每个字符串都有一个“上下文”,用于跟踪字符串所依赖的内容(实际上是在其后面的 .drv 路径列表)。

例如,GNU hello 包中的字符串 "/nix/store/rkvwvi007k7w8lp4cc0n10yhlz5xjfmk-hello-2.10" 有一些不可见状态,这表示它依赖于 hello 派生。如果该字符串最终作为 stdenv.mkDerivation 的输入,则新生成的派生将“神奇地”依赖于正在构建的 hello 包。

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

您可以使用builtins.unsafeDiscardStringContext 摆脱字符串的依赖上下文。

发生在nix 代码中的位置

${} 插值使用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;
}

toString 是用prim_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);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-05-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-20
    • 2021-02-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多