Feat/支持fnm nvm #663
Reference in New Issue
Block a user
Delete Branch "feat/support-more-node"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
close #648
1
environment_check.rs:565lts/<codename>被当成匹配任意版本.nvmrc写lts/iron时,因为任意lts/前缀都短路成Some(true),会对每个已安装版本都“匹配”;而版本文件 pin 是权威的,于是静默选中最高安装版本(如 22)。建议区分lts/*与lts/<codename>。version_matches_pin里matches!(..., "lts/*") || lower.starts_with("lts/")一起return Some(true);select_pinned_installation从Some(true)的候选里取最高版本,resolve_pinned_managed_runtime对Matched直接采用。所以lts/iron确实会选中已安装最高版本,而不是 Node 20。lts/*仍匹配任意;lts/<codename>返回None(按“未 pin”回退到 PATH / 回退链)。没有硬编码 codename → 版本行映射表(该表会过期,是另一个决策)。d905fa1c0;单测覆盖lts/iron回退、lts/*仍匹配,并把lts/iron加入“不支持 pin 回退”用例。2
command_exec.rs:2645新增测试npm_command_targets_node_plus_npm_cli_on_linux非 hermeticresolve_node_runtime,需要真实宿主 Node;在没有 Node 的 Linux CI runner 上.unwrap()会 panic。建议像其它真机测试一样早退。process_session/tests.rs有约 10 处非 opt-in 测试同样resolve_project_command_spec_at(..., "npm", ...)并unwrap(),整个 shell bin 的 Linux 单测早已依赖宿主 Node。npm run check:native-shells:agc-rust-shard-*驱动,runner 必有 Node;只给这一条测试加早退,会把同一个依赖静默漏掉、降低信号,也与既有测试口径不一致。let Ok(spec) = ... else { return }即可;但要连同process_session一起处理才有实际意义。3
command_sandbox.rs:563npm install 联网判定只看第一个参数的 basename(安全)command.exec对非node程序的参数不做路径校验,node本身只约束args[1..];因此第一个参数可以是一个叫npm-cli.js的项目文件,后面跟install,就会给非可信 npm CLI 打开--share-net。建议绑定到ProjectCommandSpec::node_launcher的真实npm_cli路径。command_sandbox_requests_npm_install(executable, arguments)对非 npm 可执行文件仅做arguments[0].file_name() == "npm-cli.js"+arguments[1] == "install";prepare_linux_command_sandbox_launch/build_linux_bwrap_launch用它决定是否--share-net。project_command_validate_arguments在#[cfg(target_os = "linux")]分支直接Ok(())(外部路径 / 敏感路径校验只在非 Linux 生效),project_command_actual_arguments在 Linux 也原样返回spec.arguments。所以program="node"+args=["/项目/game/npm-cli.js","install"]会被判为联网;项目根可写,模型能创建这个文件。.filter(|path| path.is_absolute())不够——绝对路径的项目内npm-cli.js仍会绕过,必须做前缀 / 身份校验。prepare_command_sandbox_launch新增trusted_npm_install: Option<(&Path, &Path)>,prepare_project_command_launch_spec把spec.node_launcher的(node, npm_cli)透传给沙箱;command_sandbox_requests_npm_install只在 executable、首个参数、install子命令都与可信对逐字一致时返回 true,拿不到可信对时一律不放网;LinuxSandboxPlan用npm_install_network承载结果,build_linux_bwrap_launch直接采用。f6e3e19cd(同步技术方案 V1.11.2、decision-log、pitfalls;全量 shell bin 单测 1972 passed,opt-in 真机 fnm 用例通过)。4
environment_check.rs:679fnm default 别名default存成内容为版本字符串(如v20.11.0/20)的文件,不是路径 / 符号链接;validate_node_installation_prefix会拒绝它,于是 default 别名被静默忽略、总回退到最高版本。建议像 nvm 分支那样读文件内容再select_pinned_installation。fnm/aliases/default是符号链接:default -> /root/.local/share/fnm/node-versions/v22.23.3/installation(file报 “symbolic link to ...”,readlink -f落到 installation)。validate_node_installation_prefix会 canonicalize 成 installation,bin/node与lib/node_modules/npm/bin/npm-cli.js都在,校验通过,随后installed.iter().find(prefix == ...)命中——default 别名是生效的。fs::read_to_string对“指向目录的符号链接”会报错并跳过,等于把能用的 default 别名改坏。fnm_default_alias_symlink_selects_the_linked_installation,断言 default 跟随符号链接选中 v20 而非最高的 v22。6f4667d96。5
environment_check.rs:658FNM_MULTISHELL_PATH检测不到活动 fnm 版本FNM_MULTISHELL_PATH指向一堆符号链接二进制,不是含bin/+lib/node_modules/npm的安装前缀;validate_node_installation_prefix总是拒绝它,因此永远检测不到活动 fnm 版本。建议解析其中的node符号链接并上溯到安装前缀。bin/node(普通文件)与lib/node_modules/npm/bin/npm-cli.js,所以validate_node_installation_prefix是通过的,不是“总是拒绝”。bin/node不是符号链接(ls -la显示为普通文件),canonicalize不会回到 installation;bin/npm是相对符号链接,也停在 multishell 内。active_managed_prefix()返回的 multishell 前缀与installed_node_versions枚举出的node-versions/<ver>/installation前缀不相等,随后的installed.iter().find(|node| node.prefix == prefix)落空,于是继续走默认别名 / 最高版本。resolve_managed_fallback_runtime(先看 PATH,PATH 没有再走这里)里体现;正常情况下 PATH 里的 fnm multishell 已由resolve_host_path_runtime解析到真实安装,所以实际影响低。active_managed_prefix()及其调用分支,回退链收敛为engines最高匹配 > 默认别名 > 已安装最高版本;活动版本不单独查询,因为激活时它已经在PATH里。deecebf0b(同步 decision-log、里程碑与两处技术方案口径;全量 shell bin 单测 1971 passed)。