Nix 2.23.0 发布说明全解析:`builtins.warn`、浅克隆 fetchTree、派生 JSON 格式修订与新警告机制
Nix 2.23.0 发布说明全解析builtins.warn、浅克隆 fetchTree、派生 JSON 格式修订与新警告机制【免费下载链接】nixNix, the purely functional package manager项目地址: https://gitcode.com/gh_mirrors/ni/nix本篇技术指南以 Nix 2.23.0发布于 2024-06-03的官方发布说明为主线逐一剖析该版本引入的核心变更全新内建函数builtins.warn及其配套调试选项、fetchTree默认浅克隆 Git 仓库、nix derivation {add,show}JSON 格式修订、命令行任意位置未知设置的警告、nix env shell命令重组、Store Object Info JSON 的null语义以及大路径拷贝警告阈值。读完本文你将能准确理解这些变更的行为差异、底层实现依据附仓库源码路径与升级后可能受影响的脚本和配置从而平滑迁移到 Nix 2.23。一、新内建函数builtins.warnbuiltins.warn是 2.23.0 引入的全新内建函数对应 PR NixOS/nix#10592。它在行为上等价于builtins.trace warning: ${msg}但拥有准确的日志级别真正的警告级别而非 trace 级别并受三个新配置项控制。1.1 语义与签名builtins.warn接受两个参数第一个参数e1必须是字符串求值后将其打印到标准错误stderr作为警告第二个参数e2作为函数结果返回。其语义与trace的差异在于warn只接受字符串消息而trace可以打印任意值的抽象语法表示。这一限制是有意为之——在 primops.cc 的源码注释中说明值的格式化打印场景由trace覆盖warn只接受字符串以便未来版本在不破坏既有代码的前提下增加更多功能。1.2 三个控制选项选项默认值作用debugger-on-tracefalse开启后配合--debuggerbuiltins.trace、builtins.traceVerbose需trace-verbose与builtins.warn都会像builtins.break一样进入交互式调试器debugger-on-warnfalse开启后配合--debugger仅builtins.warn进入调试器适合排查第三方 Nix 代码中的警告abort-on-warnfalse开启后builtins.warn打印警告即抛出错误从而得到指向警告位置的堆栈跟踪三个选项的完整说明见 eval-settings.hh 中的Setting定义。其中abort-on-warn尤其适合非交互场景当 Nix 被脚本调用、无法启动交互式调试器时可以通过环境变量NIX_ABORT_ON_WARN1开启该选项用堆栈跟踪定位第三方 Nix 代码中的警告来源。1.3 源码级行为验证在 primops.cc 中prim_warn的实现逻辑依次为强制求值第一个参数为字符串出错信息为 “while evaluating the first argument; the message passed to builtins.warn”以lvlWarn级别构造ErrorInfo并调用logWarning即使用真正的警告日志级别若builtinsAbortOnWarn开启抛出EvalBaseError刻意不使用EvalError子类避免错误被写入 eval 缓存并调用debugThrow中止求值若builtinsTraceDebugger或builtinsDebuggerOnWarn开启启动调试 REPL求值并返回第二个参数。从实现细节可以看到warn与trace的区别不只是“换了个名字”日志级别、是否触发调试器、是否中止求值都是独立可配置的这让包作者可以在不污染 trace 输出的前提下向用户发出可被工具捕获的结构化警告。二、nix build --keep-going与nix-build行为对齐2.23.0 修复了nix build --keep-going与旧命令nix-build --keep-going行为不一致的问题。此前当多个 fixed-output derivationFOD固定输出派生式构建失败时nix build只报告部分失败信息对齐之后所有失败的哈希不匹配hash mismatch都会被完整列出方便一次定位所有上游缓存/镜像的问题。这对依赖大量 FOD例如下载源码包、预编译产物的项目尤为重要CI 中遇到多个哈希不匹配时无需反复迭代构建即可一次性看到全部错误。三、nix derivation {add,show}JSON 格式修订对应 Issue NixOS/nix#9866。3.1 变更核心拆分hashAlgo与method对于内容寻址content-addressed的派生输出原来用一个晦涩的:分隔字段同时编码哈希算法与内容寻址方法现在拆分为两个独立字段hashAlgo与method语义清晰、便于程序化消费。序列化与反序列化的具体实现见 derivation/json.cc输出侧to_jsonCAFloating浮动哈希与Impure输出分别写出method与hashAlgo字段Impure额外带impure: true输入侧from_json根据字段集合区分输出类型——仅有path为输入寻址输出{method, hash}为固定内容寻址输出{method, hashAlgo}为浮动内容寻址输出需启用ca-derivations实验特性{method, hashAlgo, impure}为 impure 输出需启用dynamic-derivations且 text-hashed 输出同样需要该特性。3.2 适用范围与演进预期该 JSON 格式目前仅由实验性的nix derivation命令族使用如nix derivation add、nix derivation show。官方说明明确指出即便经过此次修订格式仍未完全符合数据建模规范未来版本还会继续演进——因此不应将当前字段视为稳定公共 API脚本若依赖此格式应做好兼容性处理。四、命令行任意位置未知设置的警告此前nix命令只在部分位置检测未知的--option设置导致漏报见 PR #10701。2.23.0 起所有nix命令都会在命令行任意位置对未知选项发出警告。对比示例nix-instantiate {} --option foobar baz --expr与nix eval --expr {} --option foobar baz之前静默通过现在均会输出warning: unknown setting foobar。这一改进能帮助用户尽早发现拼写错误的配置项避免“配置没生效”这类难以排查的问题。五、nix env shellCLI 子命令结构化重组nix shell在 2.23.0 中被更名为nix env shell对应 Issue NixOS/nix#10504 与 PR NixOS/nix#10807这是 CLI 子命令结构化调整的一部分nix env家族专注进程环境未来可能加入nix env run、nix env print-env等命令nix shell仍作为别名保留已有脚本与习惯用法不受影响该设计与规划中的nix dev shell即现在的nix develop形成对照后者关注开发环境的构建与运行功能更强大但需要更多配置。对日常使用而言这条变更主要是命令命名空间的迁移无需立即改动现有用法。六、Flake 输出错误信息附带值与类型当 flake 期望输出派生式却得到其他值时错误信息现在会打印失败的值及其类型对应 PR NixOS/nix#10778。变更前error: flake output attribute nixosConfigurations.yuki.config is not a derivation or path变更后error: expected flake output attribute nixosConfigurations.yuki.config to be a derivation or path but found a set: { appstream «thunk»; assertions «thunk»; boot { ... }; «48 attributes elided» }对于 NixOS 配置等大型 attribute set错误信息会展示 set 的键名并省略具体 thunk 内容如«43 attributes elided»让用户一眼看出“传错了整个 config set 而不是某个 derivation”大幅降低排查成本。七、fetchTree默认浅克隆 Git 仓库builtins.fetchTree在 2.23.0 起默认浅克隆shallow cloneGit 仓库对应 PR NixOS/nix#10028在许多场景下显著减少网络流量与磁盘占用。7.1 行为变化之前默认克隆某个 tag 或分支ref的完整历史随后才提取指定 revision 的文件现在默认浅克隆ref与allRefs参数将被忽略除非显式设置shallow false关闭浅克隆builtins.fetchGit的默认行为不变仍需手动传入shallow true启用浅克隆。7.2 源码印证浅克隆的实现贯穿 libfetchers/git.cc 与 libfetchers/git-utils.ccflake 输入解析中shallow属性来自 URL 参数如?shallow1见 git.cc 的url.query.insert_or_assign(shallow, 1)或属性集对builtins.fetchGit走getShallowAttr默认falsegit.cc对builtins.fetchTree则默认启用浅克隆仓库会复用独立的缓存路径getCachePath为浅克隆缓存附加-shallow后缀git.cc避免与完整克隆互相污染需要注意浅克隆仓库无法提供revCount访问时会抛出%s is a shallow Git repository, so revCount is not available错误git.cc若仓库中嵌套引用了浅克隆不完整的历史git-utils.cc 的错误提示会引导用户为 flake URL 增加?shallow1或为builtins.fetchGit显式设置shallow true。依赖revCount的表达式例如基于提交数计算版本号在升级后需要检查若fetchTree默认浅克隆导致revCount不可用应显式传shallow false或改用其他版本信息来源。八、Store Object Info JSON用null替代字段省略Store Object Info JSON 格式用于nix path-info等命令规范见 store-object-info.md在 2.23.0 起不再省略缺失字段而是显式以null表示对应 PR NixOS/nix#9995。例如非内容寻址的 store 对象之前会省略ca字段现在则输出ca: null。这一设计让记录更加“自描述”也更便于程序化消费解析器无需区分“字段缺失”与“字段存在但无值”两种状态。官方同时声明这一设计原则将延续到后续版本并已同步更新到贡献指南中的 data modeling 规范见>$ nix eval --warn-large-path-threshold 100M --expr builtins.toPath ./big-data warning: copying large path /home/user/big-data to the Nix store设置项定义见 globals.hh参数名warn-large-path-threshold类型uint64_t字节数默认值0即默认关闭警告设为1时对所有路径都发出警告路径大小按NAR 序列化后的字节数计算而非原始目录大小9.2 触发位置警告在两类拷贝路径上触发见 store-api.cc 与 store-dir-config.cc求值期将源码树拷贝进 storeaddToStore流程以及nix-store --add/nix path-info等按路径哈希的场景。实现上都会先计算 NAR 大小并与阈值比较超过阈值即产生警告。该特性用于发现求值阶段意外引入的巨大路径依赖——例如误将整个项目目录含.git、node_modules作为求值输入导致每次求值都拷贝几百 MB 数据到 store。十、升级影响小结与建议变更影响面迁移建议builtins.warn新增能力包作者可将非关键告警从trace迁移到warn配合abort-on-warn在 CI 中定位警告nix build --keep-going行为增强无需改动多 FOD 失败时信息更完整nix derivationJSON实验性命令族解析脚本需改为读取独立的hashAlgo/method字段且预期格式仍会演进未知设置警告行为增强检查nix.conf/命令行中是否误写配置项名nix env shell命令命名空间nix shell别名仍可用可渐进迁移Flake 输出错误信息错误信息增强无需改动fetchTree浅克隆行为变化依赖revCount时显式设shallow falseStore Object Info JSONnull破坏性变更path-info --json解析需兼容null字段warn-large-path-threshold新增能力按需设置阈值发现求值期大路径拷贝以上所有变更的完整官方描述均可在 rl-2.23.md 中找到涉及的具体设置项说明集中在 conf-file.mddebugger-on-trace、debugger-on-warn、abort-on-warn、warn-large-path-threshold相关内建函数用法见 builtins.md。升级前建议重点审计fetchTree浅克隆与 Store Object Info JSON 这两处可能产生破坏性影响的行为变化。【免费下载链接】nixNix, the purely functional package manager项目地址: https://gitcode.com/gh_mirrors/ni/nix创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考