Skip to content

Commit e7445bc

Browse files
bpamiriclaude
andauthored
fix(scoop): write wheels.cmd in pre_install so Scoop's bin shim step succeeds (#2603)
Scoop's install order is pre_install -> bin shim creation -> post_install. Both manifests emitted the wheels.cmd launcher in post_install, so the shim step ran first, failed with `Can't shim 'wheels.cmd': File doesn't exist.`, and aborted the install before the launcher was ever written. Surfaced on Windows as a permanently-broken `scoop install wheels-be` (and would have hit `wheels` GA the same way). Move the launcher-creation block to pre_install in the generator. Validator and README pick up the same rename. The emitted JSON manifests change by exactly one key per file; everything else (wrapper content, URLs, hashes, extract paths, banners) is byte-identical. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 167418d commit e7445bc

5 files changed

Lines changed: 22 additions & 12 deletions

File tree

tools/distribution-drafts/scoop/README.md

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,12 @@ Each install lands four payloads under Scoop's per-version app dir (`$dir`):
2323
| `lucli-0.3.7.bat` | cybersonic/LuCLI release | `$dir\` |
2424
| `sqlite-jdbc-3.49.1.0.jar` | Maven Central | `$dir\` |
2525

26-
The `post_install` PowerShell block emits a generated `$dir\wheels.cmd` wrapper.
27-
That wrapper is what Scoop's `bin` directive shims onto PATH as `wheels`.
26+
The `pre_install` PowerShell block emits a generated `$dir\wheels.cmd` wrapper.
27+
That wrapper is what Scoop's `bin` directive shims onto PATH as `wheels`. We use
28+
`pre_install` (not `post_install`) because Scoop's install order is
29+
`pre_install``bin` shim creation → `post_install` — writing `wheels.cmd` in
30+
`post_install` would fail the shim step with `Can't shim 'wheels.cmd': File
31+
doesn't exist.` and abort the install before the wrapper is ever created.
2832

2933
The wrapper, on every invocation:
3034

@@ -110,7 +114,7 @@ statements. To pull out the literal CMD content and review it:
110114
python3 -c '
111115
import json, re
112116
m = json.load(open("tools/distribution-drafts/scoop/wheels-be.json"))
113-
for stmt in m["post_install"]:
117+
for stmt in m["pre_install"]:
114118
mm = re.match(r"\$lines\.Add\(\x27(.*)\x27\)", stmt)
115119
if mm:
116120
print(mm.group(1).replace("\x27\x27", "\x27"))'

tools/distribution-drafts/scoop/build-manifests.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -134,8 +134,14 @@ def ps_quote_for_addcontent(line: str) -> str:
134134
return "$lines.Add('" + line.replace("'", "''") + "')"
135135

136136

137-
def build_post_install(channel: str) -> list[str]:
138-
"""Generate the post_install PowerShell array for the given channel."""
137+
def build_pre_install(channel: str) -> list[str]:
138+
"""Generate the pre_install PowerShell array for the given channel.
139+
140+
Emitted as `pre_install` rather than `post_install` because Scoop creates the
141+
`bin` shim after pre_install but before post_install. The wheels.cmd launcher
142+
must exist at shim-creation time, otherwise the install aborts with
143+
`Can't shim 'wheels.cmd': File doesn't exist.` and no further hooks run.
144+
"""
139145
lines = cmd_wrapper(channel)
140146
return [
141147
# Use the .NET List to avoid PowerShell's slow array-realloc pattern
@@ -183,7 +189,7 @@ def manifest_be() -> dict:
183189
}
184190
},
185191
"bin": [["wheels.cmd", "wheels"]],
186-
"post_install": build_post_install("bleeding-edge"),
192+
"pre_install": build_pre_install("bleeding-edge"),
187193
"checkver": {
188194
"url": "https://api.github.com/repos/wheels-dev/wheels-snapshots/releases?per_page=1",
189195
"jsonpath": "$[0].tag_name",
@@ -250,7 +256,7 @@ def manifest_stable() -> dict:
250256
}
251257
},
252258
"bin": [["wheels.cmd", "wheels"]],
253-
"post_install": build_post_install("stable"),
259+
"pre_install": build_pre_install("stable"),
254260
"checkver": {"github": "https://github.com/wheels-dev/wheels"},
255261
"autoupdate": {
256262
"architecture": {

tools/distribution-drafts/scoop/validate.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,10 @@ def info(msg: str) -> None:
4747

4848

4949
def extract_cmd_lines(manifest: dict) -> list[str]:
50-
"""Pull the literal CMD lines back out of the post_install array."""
50+
"""Pull the literal CMD lines back out of the pre_install array."""
5151
cmd_lines: list[str] = []
5252
pattern = re.compile(r"^\$lines\.Add\('(.*)'\)$")
53-
for stmt in manifest.get("post_install", []):
53+
for stmt in manifest.get("pre_install", []):
5454
m = pattern.match(stmt)
5555
if m:
5656
# PowerShell single-quote escape: '' -> '
@@ -107,7 +107,7 @@ def check_url_reachable(url: str, name: str) -> None:
107107
def check_wrapper(name: str, m: dict) -> None:
108108
cmd_lines = extract_cmd_lines(m)
109109
if not cmd_lines:
110-
fail(f"{name}: post_install emits no CMD wrapper lines")
110+
fail(f"{name}: pre_install emits no CMD wrapper lines")
111111
return
112112

113113
joined = "\n".join(cmd_lines)

tools/distribution-drafts/scoop/wheels-be.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
"wheels"
4545
]
4646
],
47-
"post_install": [
47+
"pre_install": [
4848
"$lines = New-Object System.Collections.Generic.List[string]",
4949
"$lines.Add('@echo off')",
5050
"$lines.Add('setlocal enabledelayedexpansion')",

tools/distribution-drafts/scoop/wheels.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
"wheels"
4848
]
4949
],
50-
"post_install": [
50+
"pre_install": [
5151
"$lines = New-Object System.Collections.Generic.List[string]",
5252
"$lines.Add('@echo off')",
5353
"$lines.Add('setlocal enabledelayedexpansion')",

0 commit comments

Comments
 (0)