mirror of
https://github.com/czcdr/dsh-plugin-rea.git
synced 2026-11-07 10:25:59 -10:00
fix: report an outdated bundle instead of calling it pin-consistent (2.0.10)
check-updates compared every component by major version, so 6.5.0 matched the 6.7.0 pin and the only signal that setup must be re-run disappeared. Dotted pins now compare exactly; a major-only pin (jdk 21) still matches its family; an adopted (reused) Node is checked against engines and is never counted as pin-consistent. Also: the screenshot generator reads versions from the manifest instead of hardcoding 6.5.0, and both READMEs state the two standing upgrade rules (the mirrored launcher self-heals from 2.0.8; the mirrored setup copy is refreshed only by running setup from the plugin directory).
This commit is contained in:
1 parent
7087d059be
commit
2546cca893
8 files changed
+220
-10
No files matched your search
+42
-4
@@ -2,10 +2,24 @@
|
||||
|
||||
本插件遵循语义化版本。版本号变化说明「配置组合」这层的变化,与 REA 自身的版本无关。
|
||||
|
||||
## 2.0.10 — 未发布(仓库已更新,未打 tag / 未发 npm)
|
||||
## 2.0.10 — 2026-10-19
|
||||
|
||||
**上游 REA 钉子从 6.5.0 升到 6.7.0。包、CLI 与 MCP 契约都没变,工具数仍是 207 —— 这是上游的功能与修复升级,不是工具扩容。**
|
||||
|
||||
### 修复
|
||||
|
||||
- **`check-updates.ps1` 的版本对账是假绿**(本版最重要的「用户能看见」的修复):此前对所有组件都用
|
||||
「主版本前缀」比对,`"6.5.0".StartsWith("6.")` 为真 —— 插件已钉 6.7.0、bundle 里还是 6.5.0 时,这一行报
|
||||
「与 pin 一致」。**这正好打掉 2.0.10 自己的升级场景**:用户跑完检查也看不到「该重跑 setup」,机器上再没有
|
||||
第二个信号(shim 只比「系统 REA vs 已供给」,不比 pin)。apktool 同理(盘上 3.0.9 对 pin 3.0.3 也假绿)。
|
||||
现在:带点的 pin 一律**精确比对**;只有 pin 本身只有主版本号(`jdk: 21`)才按 `21.` 前缀匹配。
|
||||
`--reuse` 采纳的本机 Node 不再拿「下载版本」精确比对(那会误报),改为对 **engines** 对账:满足则单列一行、
|
||||
不计入「全绿」,不满足则报动作。规则抽到 `scripts/pin-match.ps1`,`verify-branch.ps1` 直接 dot-source 同 7 组
|
||||
用例做回归(含 6.5.0/6.7.0、3.0.9/3.0.3、`21.0.12.1+1`/`21`)。
|
||||
- `assets/make-screenshots.ps1` 里硬编码的 `6.5.0`:版本号改为从 `manifest` 的 pins 读取(工具数 207 仍是人工
|
||||
核对常量,注释里写明升 pin 时要一起核)。`screenshot-1.png` 用同一脚本重绘,只有这两行文字变化;
|
||||
`screenshot-2.png` 重绘后逐字节不变,未改动。
|
||||
|
||||
### 变更
|
||||
|
||||
- `pins.reaAgents` 与 `components.reaAgents.sources.npm.version` → **6.7.0**(npm `latest`;6.6.0 只有 GitHub tag,
|
||||
@@ -22,11 +36,35 @@
|
||||
- 文档:两份 README 的 REA 版本与工具数、`docs/bundle-design.md` 的实测环境同步到 6.7.0;README 的钉版本示例
|
||||
跟到 `#v2.0.10`。
|
||||
|
||||
### 升级
|
||||
|
||||
> **两条长期规则 —— 本版如此,以后每个 2.x 版本都如此。**
|
||||
>
|
||||
> 1. 行执行的是 `<DSH_HOME>/plugins/rea-bundle/bin/rea-shim.mjs`,那是 setup 复制的**副本**:市场升级只换包、
|
||||
> 不换它,副本可能一直跑旧代码而**没有症状**。从 **2.0.8** 起副本会与 `mirror.json` 记录的启动器比对,不同就
|
||||
> 一跳转发执行插件里的那份(`REA_BUNDLE_SHIM_REEXEC` 守卫);**2.0.0–2.0.7 做不到**,从它们升级仍需跑一次
|
||||
> `node scripts/setup.mjs`。`--shim-status` 报 `mirror.stale`,`check-updates.ps1` 提示重跑。
|
||||
> 2. 镜像的 `scripts/setup.mjs` 也是副本、**不会自愈**:从 bundle 根目录跑的是建 bundle 那一版;要从**插件目录**
|
||||
> 跑一次刷新它。从 **2.0.9** 起它会像 shim 一样剥掉 `mirror.json` / `bundle.json` 的 UTF-8 BOM。
|
||||
|
||||
- `setup.mjs` **只对齐 bundle,不更新插件包**:它读的是「当前已安装插件」的 manifest,所以装着 2.0.9 时跑 setup
|
||||
仍旧供给 6.5.0,哪怕 2.0.10 已发布。插件包只能从市场(或 `npm i -g dsh-plugin-rea@<版本>` / `file:` 重装)换。
|
||||
- 已供给的机器**不会自动换到 6.7.0**:auto-provision 只在「未供给」时触发。重跑一次 `node scripts/setup.mjs`
|
||||
(或只补 REA:`node scripts/setup.mjs --only reaAgents`),探针会拒收盘上的 6.5.0 并重装。
|
||||
修好上面那条对账后,`npm run check-updates` 会直接报
|
||||
`reaAgents 盘上为 6.5.0,manifest 已钉 6.7.0 —— 重跑 setup 对齐`。
|
||||
|
||||
### 验证
|
||||
|
||||
- 单测 **71 条**(68 过 + 3 平台跳过);`verify-branch.ps1` 44 项全绿;`audit-manifest` clean;
|
||||
`host-compat` 10 covered / 5 outside。
|
||||
- 未发版:无 tag / 无 Release / npm 仍 **2.0.9**。
|
||||
- 单测 **71 条**(68 过 + 3 平台跳过);`verify-branch.ps1` **53 项**全绿(新增 §5b 的 2 项结构检查 + 7 组
|
||||
pin 用例);`audit-manifest` clean;`host-compat` 10 covered / 5 outside。
|
||||
- 对账修复的实证(不是读代码推断):临时 bundle 记 6.5.0、manifest 钉 6.7.0 时实跑 `check-updates.ps1`,输出
|
||||
`reaAgents 盘上为 6.5.0,manifest 已钉 6.7.0 —— 重跑 setup 对齐`,且**不再**打印「所有组件与 pin 一致」;
|
||||
`--reuse` 采纳的 Node 24.11.1 单列为「满足 engines」(不并入全绿),20.0.0 则报动作。
|
||||
- `npm pack` **22 文件**(新增 `scripts/pin-match.ps1`;`screenshot-1.png` 重绘后 68,067 B);发行资产名仍是
|
||||
版本无关的 `dsh-plugin-rea.tgz`。
|
||||
- 发布:tag `v2.0.10` → GitHub Release(资产 `dsh-plugin-rea.tgz`)→ npm `2.0.10`;插件市场按 npm 包名与
|
||||
`releases/latest/download` 两条路径解析。
|
||||
|
||||
## 2.0.9 — 2026-10-18
|
||||
|
||||
|
||||
@@ -216,6 +216,17 @@ To pin a different launch command on this machine (for example your own globally
|
||||
the row from the profile's own `cordis.patch.yml` — that file is machine-local and never published. Only one
|
||||
row may use `serverName: rea` in a profile.
|
||||
|
||||
A patch replaces the row's `config` **wholesale** — it does not deep-merge — so a partial override such as
|
||||
`config: {env: {...}}` also deletes `command`, `args` and `serverName`, and the row stops starting. Supply the
|
||||
complete config, or use `REA_BUNDLE_LAUNCH=system` (above), which needs no patch at all.
|
||||
|
||||
Ghidra and the JDK are not read from your environment at launch: `setup.mjs` records their absolute paths in
|
||||
`bundle.json` and the shim exports `GHIDRA_INSTALL_DIR` / `JAVA_HOME` from that record — which is why a
|
||||
non-standard install location works without touching the row. To adopt an existing install, point
|
||||
`GHIDRA_INSTALL_DIR` / `JAVA_HOME` at it and run `node scripts/setup.mjs --reuse`: the manifest's probe checks
|
||||
the candidate and falls back to a download when it does not match, so a wrong path is reported during setup
|
||||
instead of failing later inside a tool call.
|
||||
|
||||
### One REA registration only
|
||||
|
||||
Upstream REA 6.5.0 can register itself with DSH:
|
||||
@@ -302,6 +313,26 @@ macOS/Linux.
|
||||
|
||||
## Updating — three independent things
|
||||
|
||||
> **Two standing rules — for this release and for every later 2.x release.**
|
||||
>
|
||||
> `setup.mjs` reconciles the **bundle**, never the **plugin**: it reads the manifest of the plugin that is
|
||||
> installed *right now*. Installed 2.0.9? setup provisions 6.5.0 even after 2.0.10 exists. The package changes
|
||||
> only through the market (or `npm i -g dsh-plugin-rea@<version>` / a `file:` reinstall); running setup more
|
||||
> often never substitutes for that.
|
||||
>
|
||||
> 1. **The row executes a copy of this plugin's launcher.** `<DSH_HOME>/plugins/rea-bundle/bin/rea-shim.mjs` is a
|
||||
> mirror made by setup, and a market upgrade replaces the package without replacing it — so the mirror can keep
|
||||
> running old code with **no symptom at all**. Since **2.0.8** the mirror compares itself with the launcher
|
||||
> recorded in `mirror.json` and re-execs the plugin's copy when the two differ (one hop, guarded by
|
||||
> `REA_BUNDLE_SHIM_REEXEC`). A mirror **older than 2.0.8 cannot do this**, so upgrading from **2.0.0–2.0.7**
|
||||
> still needs one `node scripts/setup.mjs`. `--shim-status` reports `mirror.stale`; `check-updates.ps1` says
|
||||
> when to re-run.
|
||||
> 2. **The mirrored `scripts/setup.mjs` is a copy too, and it has no self-heal of its own.** Running setup from the
|
||||
> bundle root therefore executes the version from when the bundle was created, not the one you just installed.
|
||||
> Run it once **from the plugin directory** to refresh that copy. Since **2.0.9** the copy strips the UTF-8 BOM
|
||||
> from `mirror.json` / `bundle.json` exactly as the shim does, so a BOM-ed record no longer reads as "no record"
|
||||
> on the setup side (which used to re-mirror the previous manifest).
|
||||
|
||||
### Updating from the market
|
||||
|
||||
Update it where you installed it. Updating **to 2.0.5 or later** is routine; updating an installed 2.0.1–2.0.4
|
||||
|
||||
@@ -203,6 +203,14 @@ node bin/rea-shim.mjs --shim-print-env # MCP 子进程将看到的环境变量
|
||||
`cordis.patch.yml` 按 id 覆盖即可 —— 那个文件是机器本地的,永不发布。一个 profile 里只允许一行使用
|
||||
`serverName: rea`。
|
||||
|
||||
覆盖是**整块替换** `config`(不做深合并):只写 `config: {env: …}` 会把 `command`、`args`、`serverName`
|
||||
一起删掉,这一行就起不来了。要么写完整的 config,要么改用 `REA_BUNDLE_LAUNCH=system`(见上),它不需要改 patch。
|
||||
|
||||
Ghidra 和 JDK **不是启动时从环境里读的**:`setup.mjs` 把它们的绝对路径记进 `bundle.json`,shim 再从那份
|
||||
记录导出 `GHIDRA_INSTALL_DIR` / `JAVA_HOME` —— 所以装在非标准路径也能用,不必动这一行。要采纳现成的安装,
|
||||
把 `GHIDRA_INSTALL_DIR` / `JAVA_HOME` 指向它并跑 `node scripts/setup.mjs --reuse`:manifest 里的探针会验证
|
||||
候选,不符合就回落到下载,**路径写错会在供给时就报出来**,而不是等到某次工具调用里才失效。
|
||||
|
||||
### 只保留一条 REA 注册
|
||||
|
||||
上游 REA 6.5.0 起可以自己注册进 DSH:
|
||||
@@ -283,6 +291,22 @@ shim** 的 MCP `initialize` 握手返回 `serverInfo {name: rea, version: 6.7.0}
|
||||
|
||||
## 更新 —— 三件互相独立的事
|
||||
|
||||
> **两条长期规则 —— 本版如此,以后每个 2.x 版本都如此。**
|
||||
>
|
||||
> `setup.mjs` 只对齐 **bundle**,不更新**插件包**:它读的是「当前已安装插件」的 manifest。装着 2.0.9 时跑 setup
|
||||
> 仍旧供给 6.5.0,哪怕 2.0.10 已经发布。插件包只能从市场(或 `npm i -g dsh-plugin-rea@<版本>` / `file:` 重装)换,
|
||||
> **多跑几次 setup 也替代不了那一步**。
|
||||
>
|
||||
> 1. **行执行的是本插件启动器的「镜像副本」**:`<DSH_HOME>/plugins/rea-bundle/bin/rea-shim.mjs` 由 setup 复制,
|
||||
> 市场升级只换包、不换它,所以副本可能一直跑旧代码而**完全没有症状**。从 **2.0.8** 起,副本会与 `mirror.json`
|
||||
> 记录的启动器比对,不同就一跳转发执行插件里的那份(带 `REA_BUNDLE_SHIM_REEXEC` 守卫)。**2.0.0–2.0.7 的镜像
|
||||
> 做不到**,所以从它们升级仍需跑一次 `node scripts/setup.mjs`。`--shim-status` 会报 `mirror.stale`,
|
||||
> `check-updates.ps1` 会提示重跑。
|
||||
> 2. **镜像的 `scripts/setup.mjs` 同样是副本,而且它自己不会自愈**:从 bundle 根目录跑它,跑的是建 bundle 那一版
|
||||
> 的 setup,不是你刚装的这一版。要从**插件目录**跑一次来刷新这份副本。从 **2.0.9** 起,它会像 shim 一样剥掉
|
||||
> `mirror.json` / `bundle.json` 的 UTF-8 BOM —— 带 BOM 的记录以前在 setup 眼里等于「没有记录」,会把上一版
|
||||
> manifest 又镜一遍。
|
||||
|
||||
### 在市场里更新
|
||||
|
||||
在哪儿装的就在哪儿更新。更新到 **2.0.5 及以上**是常规操作;而把已装的 2.0.1–2.0.4 通过应用内市场**更新到
|
||||
|
||||
@@ -19,6 +19,28 @@ param([string]$OutDir)
|
||||
# actually regenerated a screenshot. Resolve the default in the body instead.
|
||||
if (-not $OutDir -or $OutDir.Trim() -eq '') { $OutDir = $PSScriptRoot }
|
||||
|
||||
# 版本号从 manifest 读,不再手写成固定值。2.0.10 就踩过:pin 升到 6.7.0 之后,
|
||||
# 这个脚本还写着 6.5.0 —— 现有 PNG 没问题(它们是 6.5.0 时生成的),但下一次
|
||||
# 重绘会把旧版本号带进市场页,而且没有人会注意到,因为图片是二进制。
|
||||
# 工具数(207)不是 manifest 字段,是人工核对过的常量:升 pin 时一起核一遍。
|
||||
$reaPin = '6.7.0'
|
||||
$reaTools = 207
|
||||
$ghidraPin = '12.1.4'
|
||||
$nodePin = '24.21.0'
|
||||
# 截图是一次「实测」,这个日期必须是真的测量日;重绘时改成当天。
|
||||
$measuredOn = '2026-10-19'
|
||||
$manifestFile = Join-Path (Split-Path -Parent $PSScriptRoot) 'manifest\bundle.manifest.json'
|
||||
if (Test-Path $manifestFile) {
|
||||
try {
|
||||
$pinDoc = Get-Content $manifestFile -Raw -Encoding UTF8 | ConvertFrom-Json
|
||||
if ($pinDoc.pins.reaAgents) { $reaPin = [string]$pinDoc.pins.reaAgents }
|
||||
if ($pinDoc.pins.ghidra) { $ghidraPin = [string]$pinDoc.pins.ghidra }
|
||||
if ($pinDoc.pins.node) { $nodePin = [string]$pinDoc.pins.node }
|
||||
} catch {
|
||||
Write-Warning "manifest 里的钉子读不到($($_.Exception.Message));用脚本内的默认值。"
|
||||
}
|
||||
}
|
||||
|
||||
Add-Type -AssemblyName System.Drawing
|
||||
|
||||
$W = 1280; $H = 720
|
||||
@@ -84,7 +106,7 @@ Draw-Text $g '第三方适配 · 自身不做逆向分析 · 自供给 Node/REA/
|
||||
$rowY = 180; $boxH = 158; $boxW = 250
|
||||
Draw-Box $g 60 $rowY $boxW $boxH $([System.Drawing.Color]::White) $line
|
||||
Draw-Text $g 'DeepSeek Harness 会话' $fBox $ink 80 ($rowY + 18)
|
||||
Draw-Text $g "mcp__rea__* 工具`n(6.5.0 暴露 207)`n工具随会话注入`n按 DSH 权限策略执行" $fBody $muted 80 ($rowY + 50)
|
||||
Draw-Text $g "mcp__rea__* 工具`n($reaPin 暴露 $reaTools)`n工具随会话注入`n按 DSH 权限策略执行" $fBody $muted 80 ($rowY + 50)
|
||||
|
||||
Draw-Box $g 360 $rowY $boxW $boxH $([System.Drawing.Color]::FromArgb(255,239,246,255)) $accent
|
||||
Draw-Text $g '官方 MCP 客户端行' $fBox $accent 380 ($rowY + 18)
|
||||
@@ -112,7 +134,7 @@ Draw-Line $g 358 446 150 446 $muted
|
||||
Draw-Arrow $g 150 446 150 342 $muted
|
||||
|
||||
Draw-Text $g '上游 REA(MIT):github.com/morluto/rea 本插件:github.com/czcdr/dsh-plugin-rea' $fSmall $muted 60 620
|
||||
Draw-Text $g '实测 REA 6.5.0 + DSH 桌面运行时 0.2.0-rc.2 + Ghidra 12.1.4 + Node 24.21.0(Windows 11 x64,2026-10-16)' $fSmall $muted 60 646
|
||||
Draw-Text $g "实测 REA $reaPin + DSH 桌面运行时 0.2.0-rc.2 + Ghidra $ghidraPin + Node ${nodePin}(Windows 11 x64,$measuredOn)" $fSmall $muted 60 646
|
||||
Draw-Text $g 'Ghidra 为 Apache-2.0(NSA);REA 为 MIT。本仓库不分发上游代码。' $fSmall $muted 60 672
|
||||
Save-Png $bmp $g (Join-Path $OutDir 'screenshot-1.png')
|
||||
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 66 KiB After Width: | Height: | Size: 66 KiB |
+46
-4
@@ -37,6 +37,21 @@ function Get-NumericVersion([string]$v) {
|
||||
try { return [version]$core } catch { return $null }
|
||||
}
|
||||
|
||||
# 版本比对规则放在独立文件里:这一行是用户唯一能看到的「pin 变了,该重跑 setup」
|
||||
# 信号,2.0.10 之前它假绿过(6.5.0 被判成与 pin 6.7.0 一致),所以需要一条不依赖
|
||||
# 网络、不依赖 profile 的回归测试 —— verify-branch.ps1 直接 dot-source 这个文件。
|
||||
$pinMatchFile = Join-Path $PSScriptRoot 'scripts\pin-match.ps1'
|
||||
if (Test-Path $pinMatchFile) {
|
||||
. $pinMatchFile
|
||||
} else {
|
||||
# 目录不完整(旧拷贝、手工搬走了一个文件):退化为精确比对。
|
||||
# 宁可多报一次「重跑 setup」,也不能再假绿。
|
||||
function Test-PinMatch {
|
||||
param([string]$Installed, [string]$Pinned)
|
||||
return [string]::Equals(([string]$Installed).Trim(), ([string]$Pinned).Trim(), [System.StringComparison]::Ordinal)
|
||||
}
|
||||
}
|
||||
|
||||
# 判断 Node 版本是否满足 engines 字符串(支持 ^X.Y.Z / ~X.Y.Z / >=X.Y.Z,用 || 分隔)
|
||||
# 参数收 string 不收 [version]:类型约束在函数体之前生效,调用方一旦传入
|
||||
# 'abc' / '' / 'v24.21.0' 这类值就会抛 ParameterBindingArgumentTransformationException。
|
||||
@@ -322,6 +337,8 @@ if (-not (Test-Path $manifestPath)) {
|
||||
$drift = 0
|
||||
$compared = 0
|
||||
$unrecorded = 0
|
||||
# 采纳的本机运行时(reused)不按 pin 精确比对,但也不能算进「全绿」。
|
||||
$adopted = 0
|
||||
foreach ($name in $manifest.pins.PSObject.Properties.Name) {
|
||||
if ($name -eq 'nodeEngines') { continue }
|
||||
$pinned = [string]$manifest.pins.$name
|
||||
@@ -337,12 +354,37 @@ if (-not (Test-Path $manifestPath)) {
|
||||
continue
|
||||
}
|
||||
$compared++
|
||||
# Node 的 pin 是引擎范围,不是版本号;其它组件比前缀即可
|
||||
$same = $installed.Equals($pinned) -or $installed.StartsWith(($pinned -split '\.')[0] + '.')
|
||||
if ($same) { Info " $name = $installed(pin $pinned)" }
|
||||
$component = $null
|
||||
if ($state.components -and ($state.components.PSObject.Properties.Name -contains $name)) {
|
||||
$component = $state.components.$name
|
||||
}
|
||||
# 采纳的本机 Node(setup --reuse)不是 bundle 安装的版本,拿它跟「下载版本」
|
||||
# 精确比对必然误报;它要满足的是 engines。采纳时 setup 跑过同一份探针,这里
|
||||
# 再用同一个 Test-NodeEngines 对一次账,而不是把它当成「与 pin 一致」。
|
||||
if ($name -eq 'node' -and $component -and $component.reused -eq $true) {
|
||||
$engines = [string]$manifest.pins.nodeEngines
|
||||
$enginesOk = Test-NodeEngines $installed $engines
|
||||
if ($enginesOk -eq $true) {
|
||||
Info " node = $installed(采纳本机运行时;pin $pinned 指下载版本,满足 engines)"
|
||||
$adopted++
|
||||
} elseif ($enginesOk -eq $false) {
|
||||
Warn "node 盘上为 $installed(采纳的本机运行时),不满足 REA engines $engines —— 换一个 Node 或重跑 setup"
|
||||
$drift++
|
||||
} else {
|
||||
Warn "node 盘上为 $installed,但 engines 无法解析($engines)—— 未比对"
|
||||
$unrecorded++
|
||||
}
|
||||
continue
|
||||
}
|
||||
# 2.0.10 修掉的假绿:此前对所有组件都比「主版本前缀」,
|
||||
# "6.5.0".StartsWith("6.") 为真 → bundle 还在 6.5.0 时报「与 pin 6.7.0 一致」,
|
||||
# 而这行正是 pin 升级后唯一面向用户的「该重跑 setup」信号。apktool 同理
|
||||
# (3.0.9 对 pin 3.0.3 也假绿)。主版本前缀只对 pin 本身只有主版本号时成立(jdk 21)。
|
||||
if (Test-PinMatch -Installed $installed -Pinned $pinned) { Info " $name = $installed(pin $pinned)" }
|
||||
else { Warn "$name 盘上为 $installed,manifest 已钉 $pinned —— 重跑 setup 对齐"; $drift++ }
|
||||
}
|
||||
if ($drift -eq 0 -and $unrecorded -eq 0) { Ok '所有组件与 manifest 的 pin 一致' }
|
||||
if ($drift -eq 0 -and $unrecorded -eq 0 -and $adopted -eq 0) { Ok '所有组件与 manifest 的 pin 一致' }
|
||||
elseif ($drift -eq 0 -and $unrecorded -eq 0) { Warn "共比对 $compared 项:其中 $adopted 项为采纳的本机运行时(按 engines 放行,见上),其余与 pin 一致" }
|
||||
elseif ($drift -eq 0) { Warn "已比对的 $compared 项与 pin 一致,但 $unrecorded 项没有记录版本(见上)—— 不是全绿" }
|
||||
if ($state.unverifiedChecksums -and @($state.unverifiedChecksums).Count -gt 0) {
|
||||
Warn ("TOFU(无厂商校验和,取首次实测值): " + (@($state.unverifiedChecksums) -join ', '))
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
# Pin comparison for check-updates.ps1, kept in a dot-sourceable file so it can
|
||||
# be tested without running the whole check (which talks to a registry).
|
||||
#
|
||||
# Why this is a function and not an inline condition: until 2.0.10 the comparison
|
||||
# was "equal, OR shares the first dotted component with the pin", applied to every
|
||||
# component. "6.5.0".StartsWith("6.") is true, so a bundle still on 6.5.0 reported
|
||||
# "consistent with pin 6.7.0", and that line is the only signal a user has that a
|
||||
# pin bump requires re-running setup. apktool had the same shape (3.0.9 vs 3.0.3,
|
||||
# where the major-prefix test called them equal).
|
||||
#
|
||||
# The one pin that is genuinely major-only is the JDK ("21"): the download records
|
||||
# 21.0.12.1+1 and both name the same family. A dotted pin names exactly one
|
||||
# version. The reverse rule, prefix matching on a dotted pin, is the bug.
|
||||
# Kept ASCII-only on purpose: Windows PowerShell 5.1 reads a BOM-less script as
|
||||
# ANSI, and this file ships inside the package.
|
||||
function Test-PinMatch {
|
||||
param(
|
||||
[string]$Installed,
|
||||
[string]$Pinned
|
||||
)
|
||||
$installed = ([string]$Installed).Trim()
|
||||
$pinned = ([string]$Pinned).Trim()
|
||||
if ($installed -eq '' -or $pinned -eq '') { return $false }
|
||||
$same = [string]::Equals($installed, $pinned, [System.StringComparison]::Ordinal)
|
||||
if ($pinned.Contains('.')) { return $same }
|
||||
# A major-only pin ("21") also matches its point releases ("21.0.12.1+1").
|
||||
return ($same -or $installed.StartsWith($pinned + '.', [System.StringComparison]::Ordinal))
|
||||
}
|
||||
@@ -94,6 +94,31 @@ if (bad.length) {
|
||||
& node $jsProbe 2>&1 | ForEach-Object { Write-Host " $_" -ForegroundColor Gray }
|
||||
Check 'evaluated literals contain no control characters' ($LASTEXITCODE -eq 0) 'see above'
|
||||
|
||||
Write-Host "`n=== 5b. the pin comparison is not a major-prefix match ===" -ForegroundColor Cyan
|
||||
# 2.0.10 shipped a false green here: "6.5.0".StartsWith("6.") is true, so a bundle
|
||||
# still on 6.5.0 reported "consistent with pin 6.7.0" — and that line is the only
|
||||
# signal a user has that a pin bump requires re-running setup. The rule lives in
|
||||
# scripts/pin-match.ps1 so it can be checked without the registry/profile sections.
|
||||
$pinMatchFile = Join-Path $root 'scripts\pin-match.ps1'
|
||||
Check 'scripts/pin-match.ps1 exists' (Test-Path $pinMatchFile) ''
|
||||
Check 'check-updates.ps1 uses Test-PinMatch' ((Get-Content (Join-Path $root 'check-updates.ps1') -Raw -Encoding UTF8) -match 'Test-PinMatch') ''
|
||||
if (Test-Path $pinMatchFile) {
|
||||
. $pinMatchFile
|
||||
$pinCases = @(
|
||||
@('6.5.0', '6.7.0', $false, 'older REA under a newer pin must not be a match'),
|
||||
@('6.7.0', '6.7.0', $true, 'exact match'),
|
||||
@('3.0.9', '3.0.3', $false, 'apktool above the pin must not be a match'),
|
||||
@('21.0.12.1+1', '21', $true, 'major-only jdk pin names the family'),
|
||||
@('21', '21', $true, 'exact major-only pin'),
|
||||
@('24.11.1', '24.21.0', $false, 'a dotted node pin is one version'),
|
||||
@('', '6.7.0', $false, 'no recorded version is never a match')
|
||||
)
|
||||
foreach ($c in $pinCases) {
|
||||
$got = Test-PinMatch -Installed $c[0] -Pinned $c[1]
|
||||
Check ("pin '{0}' vs '{1}' -> {2}" -f $c[0], $c[1], $c[2]) ($got -eq $c[2]) ("got ${got}: {0}" -f $c[3])
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host "`n=== 6. package payload lists what the bundle needs ===" -ForegroundColor Cyan
|
||||
# -Encoding UTF8 is required: the package description contains CJK text, and
|
||||
# PowerShell 5.1 reads a BOM-less file as ANSI, which breaks ConvertFrom-Json.
|
||||
|
||||
Reference in new issue
Block a user