Windows setup-runner shell¶
在原生 Windows 上,Orca 会将 orca.yaml setup 脚本(以及 issue 命令)写入一个生成的
runner 文件,并在终端中输入一条启动命令。runner 默认是一个 .cmd 批处理文件,
自 setup 钩子发布以来一直如此。
脚本通过以 #! 解释器行开头来选择 bash:
如果没有该行,脚本仍会在 cmd.exe 下运行:
为什么由脚本声明,而不是终端偏好¶
terminalWindowsShell 指定_交互式终端_打开时使用哪个 shell。它并不说明项目的 setup 脚本是用
什么语言编写的。从它推导 runner 曾导致两个后果:
- 拥有批处理语法 setup 脚本的 Windows 用户在升级后会被静默切换到 bash,因此
copy、xcopy、set VAR=value和if errorlevel 1不再可用。 - 同一仓库中的两个人会为同一个
orca.yaml得到不同的解释器,因此没有任何项目能编写一个 对所有 Windows 贡献者都有效的 setup 脚本。
#! 行是按项目设置的、显式的,并且对所有检出该仓库的人都相同。
同一规则也适用于 设置 → 仓库钩子 中的按用户 setup 命令
(repo.hookSettings.scripts.setup):它会被合并到到达 runner 的同一个脚本中,因此存储在那里的
POSIX 单行命令需要自己的 #! 行才能在 Windows 上以 bash 运行。
#! 行选择什么以及不选择什么¶
生成的 runner 在所有平台上始终由 bash 执行(bash <runner>;在原生 Windows 上为 Git Bash)。
因此,#! 行做了两件事:
- 它声明脚本是为 POSIX shell 编写的,这正是选择 bash runner 的依据。
- 它的选项标志会通过
set重放,因此#!/usr/bin/env -S bash -euo pipefail确实会获得pipefail。如果没有这种重放,这些标志会被静默丢弃,因为bash <runner>从不解析解释器行。 只有set本身接受的标志([--abefhkmnptuvxBCHP] [-o option])会被重放;仅用于启动的标志 (例如-l)会被丢弃,因为set -l会以退出码 2 退出,并会在 runner 的第一行之前中止 runner。
解释器名称本身除了“这是否是 POSIX shell”之外不会被遵循:#!/bin/sh 和
#!/bin/zsh 脚本会在 bash 下运行,正如它们在 macOS 和 Linux 上已经那样做。
bash runner 的要求¶
#! 行只有在 Orca 确实能够从已配置的终端启动 bash 时才生效——终端 shell 必须解析为 Git Bash
(resolveWindowsGitBashShellPath)。生成的 runner 使用 MSYS /c/... 路径,Cygwin 和 WSL shim
不接受这些路径,并且启动命令会被输入到终端打开的任意 shell 中。
当 bash 不可用时(PowerShell/cmd 终端,或 SSH 到 Windows 的主机,后者始终使用远程的 .cmd
runner),#! 脚本不会在 cmd 下执行。生成的 .cmd runner 会打印原因并以退出码 1 退出,
因为运行 bash 脚本中与解释器无关的前缀(pnpm install、git submodule update),却只在第一条
仅 bash 可用的行上失败,会留下一个看似已完成但只设置了一半的 worktree。
从 Git Bash 终端启动 .cmd runner¶
runner 格式与输入启动命令的 shell 相互独立:拥有批处理语法 setup 脚本的 Git Bash 终端会得到一个
从 bash 窗格启动的 .cmd runner。cmd.exe /c
"C:\..." 不能在那里使用 — MSYS 会将裸 /c 开关重写为驱动器路径,因此 cmd 会交互式打开,
runner 永远不会执行(issue #6896)。这些启动会复用 PowerShell 的 ProcessStartInfo 启动器
(buildWindowsCmdRunnerDelayedLaunchCommand),它将开关和 runner 路径放在命令行之外。
因此,WorktreeSetupLaunch.shell 描述的是启动窗格;runner 文件的 .cmd/.sh 扩展名描述的是格式。
wait-for-setup 门控遵循同样的拆分。窗格输入门控,并且已经为自身引用了 agent 启动命令,因此从
Git Bash 窗格启动的 .cmd runner 仍然获得 bash 门控 — PowerShell 的 Invoke-Expression 无法解析
POSIX '\'' 转义。该门控包装了同一个 ProcessStartInfo 启动器,因此批处理 runner 永远不会交给 bash。
WSL worktree 和非 Windows 平台不受影响:它们始终使用 bash runner。SSH 主机根据远程路径格式选择 runner,而不是根据本地 Windows 偏好。
本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 orca48/orca