@codyswann/lisa 2.330.0 → 2.331.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +3 -15
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/standards-proof-cmd.d.ts +22 -0
- package/dist/cli/standards-proof-cmd.d.ts.map +1 -1
- package/dist/cli/standards-proof-cmd.js +18 -0
- package/dist/cli/standards-proof-cmd.js.map +1 -1
- package/dist/cli/workstation-cmd.d.ts +91 -0
- package/dist/cli/workstation-cmd.d.ts.map +1 -0
- package/dist/cli/workstation-cmd.js +127 -0
- package/dist/cli/workstation-cmd.js.map +1 -0
- package/dist/core/upstream-evidence-manifest.d.ts.map +1 -1
- package/dist/core/upstream-evidence-manifest.js +9 -6
- package/dist/core/upstream-evidence-manifest.js.map +1 -1
- package/package.json +1 -1
- package/plugins/lisa/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa/.codex-plugin/skills/lisa-detect-tooling/scripts/detect-tooling.mjs +2 -1
- package/plugins/lisa/.codex-plugin/skills/lisa-setup-remote-env/SKILL.md +13 -1
- package/plugins/lisa/.codex-plugin/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +89 -0
- package/plugins/lisa/.codex-plugin/skills/lisa-setup-remote-env/scripts/toolchain.mjs +21 -1
- package/plugins/lisa/.codex-plugin/skills/lisa-setup-workstation/SKILL.md +27 -6
- package/plugins/lisa/commands/setup/workstation.md +2 -0
- package/plugins/lisa/skills/lisa-detect-tooling/scripts/detect-tooling.mjs +2 -1
- package/plugins/lisa/skills/lisa-setup-remote-env/SKILL.md +13 -1
- package/plugins/lisa/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +89 -0
- package/plugins/lisa/skills/lisa-setup-remote-env/scripts/toolchain.mjs +21 -1
- package/plugins/lisa/skills/lisa-setup-workstation/SKILL.md +27 -6
- package/plugins/lisa-agy/commands/lisa/setup/workstation.md +2 -0
- package/plugins/lisa-agy/plugin.json +1 -1
- package/plugins/lisa-agy/skills/lisa-detect-tooling/scripts/detect-tooling.mjs +2 -1
- package/plugins/lisa-agy/skills/lisa-setup-remote-env/SKILL.md +13 -1
- package/plugins/lisa-agy/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +89 -0
- package/plugins/lisa-agy/skills/lisa-setup-remote-env/scripts/toolchain.mjs +21 -1
- package/plugins/lisa-agy/skills/lisa-setup-workstation/SKILL.md +27 -6
- package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk-agy/plugin.json +1 -1
- package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-copilot/commands/lisa/setup/workstation.md +2 -0
- package/plugins/lisa-copilot/skills/lisa-detect-tooling/scripts/detect-tooling.mjs +2 -1
- package/plugins/lisa-copilot/skills/lisa-setup-remote-env/SKILL.md +13 -1
- package/plugins/lisa-copilot/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +89 -0
- package/plugins/lisa-copilot/skills/lisa-setup-remote-env/scripts/toolchain.mjs +21 -1
- package/plugins/lisa-copilot/skills/lisa-setup-workstation/SKILL.md +27 -6
- package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-cursor/commands/lisa/setup/workstation.md +2 -0
- package/plugins/lisa-cursor/skills/lisa-detect-tooling/scripts/detect-tooling.mjs +2 -1
- package/plugins/lisa-cursor/skills/lisa-setup-remote-env/SKILL.md +13 -1
- package/plugins/lisa-cursor/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +89 -0
- package/plugins/lisa-cursor/skills/lisa-setup-remote-env/scripts/toolchain.mjs +21 -1
- package/plugins/lisa-cursor/skills/lisa-setup-workstation/SKILL.md +27 -6
- package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-expo-agy/plugin.json +1 -1
- package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs-agy/plugin.json +1 -1
- package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw-agy/plugin.json +1 -1
- package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser-agy/plugin.json +1 -1
- package/plugins/lisa-phaser-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-phaser-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-agy/plugin.json +1 -1
- package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript-agy/plugin.json +1 -1
- package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki-agy/plugin.json +1 -1
- package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
- package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
- package/plugins/src/base/commands/setup/workstation.md +2 -0
- package/plugins/src/base/skills/lisa-detect-tooling/scripts/detect-tooling.mjs +2 -1
- package/plugins/src/base/skills/lisa-setup-remote-env/SKILL.md +13 -1
- package/plugins/src/base/skills/lisa-setup-remote-env/scripts/setup-remote-env.mjs +89 -0
- package/plugins/src/base/skills/lisa-setup-remote-env/scripts/toolchain.mjs +21 -1
- package/plugins/src/base/skills/lisa-setup-workstation/SKILL.md +27 -6
|
@@ -334,6 +334,26 @@ export function assertPinned(tool) {
|
|
|
334
334
|
}
|
|
335
335
|
return;
|
|
336
336
|
}
|
|
337
|
+
// A tree carries the same checksum obligation and one more: which file inside
|
|
338
|
+
// it is the entry point. There is no sane default — the archive root is a
|
|
339
|
+
// directory, so guessing would install a directory as a binary.
|
|
340
|
+
if (tool.install === "release-tree") {
|
|
341
|
+
if (!tool.url || !tool.sha256) {
|
|
342
|
+
throw new Error(
|
|
343
|
+
`${tool.name}: a release-tree install needs both url and sha256.\n` +
|
|
344
|
+
`A version bump must move the checksum in the same reviewed commit.`
|
|
345
|
+
);
|
|
346
|
+
}
|
|
347
|
+
if (!tool.binary) {
|
|
348
|
+
throw new Error(
|
|
349
|
+
`${tool.name}: a release-tree install needs "binary" — the path to the ` +
|
|
350
|
+
`entry point INSIDE the archive, such as "maestro/bin/maestro".\n` +
|
|
351
|
+
`Unlike the single-file kinds there is nothing to fall back to: the ` +
|
|
352
|
+
`archive root is a directory.`
|
|
353
|
+
);
|
|
354
|
+
}
|
|
355
|
+
return;
|
|
356
|
+
}
|
|
337
357
|
if (tool.install === "npm-global") {
|
|
338
358
|
if (!tool.package)
|
|
339
359
|
throw new Error(`${tool.name}: npm-global install needs a package`);
|
|
@@ -341,6 +361,6 @@ export function assertPinned(tool) {
|
|
|
341
361
|
}
|
|
342
362
|
throw new Error(
|
|
343
363
|
`${tool.name}: unknown install method "${tool.install}".\n` +
|
|
344
|
-
`Supported: release-zip, release-tar, npm-global.`
|
|
364
|
+
`Supported: release-zip, release-tar, release-tree, npm-global.`
|
|
345
365
|
);
|
|
346
366
|
}
|
|
@@ -25,15 +25,36 @@ repository, and nothing here duplicates that manifest.
|
|
|
25
25
|
|
|
26
26
|
## Usage
|
|
27
27
|
|
|
28
|
+
**Start here — this is the entry point that presumes nothing:**
|
|
29
|
+
|
|
30
|
+
```sh
|
|
31
|
+
npx -y @codyswann/lisa@latest workstation # report what is present and missing
|
|
32
|
+
npx -y @codyswann/lisa@latest workstation --install # install what is missing
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
That form needs only Node. No checkout, no agent, no Lisa install — npx resolves
|
|
36
|
+
the package into its own cache.
|
|
37
|
+
|
|
38
|
+
**Why it matters:** this skill exists to prepare a machine with *no coding agent*
|
|
39
|
+
and *no checkout*. But a skill can only be invoked by typing a slash command into
|
|
40
|
+
an agent, and Lisa ships as a devDependency, so it does not exist until a repo is
|
|
41
|
+
cloned and its dependencies installed. Both are exactly the state this is meant to
|
|
42
|
+
create — so as a skill alone, the bootstrap was unreachable in the one scenario it
|
|
43
|
+
was designed for. The CLI is the way in; the skill is the surface for people who
|
|
44
|
+
already have an agent.
|
|
45
|
+
|
|
46
|
+
Every flag is the same either way:
|
|
47
|
+
|
|
28
48
|
```sh
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
node scripts/cli.mjs --json # machine-readable plan
|
|
34
|
-
node scripts/cli.mjs --print-dockerfile # an image that runs this same script
|
|
49
|
+
lisa workstation --install --agents=claude,codex # only these agents
|
|
50
|
+
lisa workstation --provider=bitwarden # credential manager (asked if a TTY)
|
|
51
|
+
lisa workstation --json # machine-readable plan
|
|
52
|
+
lisa workstation --print-dockerfile # an image that runs this same script
|
|
35
53
|
```
|
|
36
54
|
|
|
55
|
+
Inside an agent, `/lisa:setup:workstation` runs the identical script; and the
|
|
56
|
+
script itself is directly runnable as `node scripts/cli.mjs …`.
|
|
57
|
+
|
|
37
58
|
Nothing is installed or written without `--install`. Exit status is non-zero when a required
|
|
38
59
|
tool is absent or an install fails, so this is usable as a gate.
|
|
39
60
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lisa-openclaw",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.331.0",
|
|
4
4
|
"description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Cody Swann"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lisa-openclaw",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.331.0",
|
|
4
4
|
"description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, across Claude and Codex.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Cody Swann"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lisa-openclaw",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.331.0",
|
|
4
4
|
"description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Cody Swann"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lisa-openclaw",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.331.0",
|
|
4
4
|
"description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Cody Swann"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lisa-openclaw",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.331.0",
|
|
4
4
|
"description": "Connect staff roles to Telegram or Slack via OpenClaw — facilitator/specialist hub-and-spoke routing and repo-coding topics, for Claude Code and Codex",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Cody Swann"
|
|
@@ -5,3 +5,5 @@ argument-hint: "[--install] [--agents=claude,codex] [--provider=bitwarden] [--js
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
Use the /lisa-setup-workstation skill to report and optionally install the coding agents, credential manager, and base tools this machine needs. $ARGUMENTS
|
|
8
|
+
|
|
9
|
+
Note: on a machine with no agent and no checkout — which is what this prepares — reach the same bootstrap without Lisa installed at all: `npx -y @codyswann/lisa@latest workstation --install`.
|
|
@@ -563,7 +563,8 @@ export function proposedEntries(proposal) {
|
|
|
563
563
|
// the checksum cannot vouch for, which is the one property that makes a
|
|
564
564
|
// pinned entry worth reviewing.
|
|
565
565
|
const archive = platform => ({
|
|
566
|
-
install:
|
|
566
|
+
install:
|
|
567
|
+
"<release-tar | release-zip | release-tree — tree when the archive is a directory whose entry point loads its own siblings>",
|
|
567
568
|
url: `<release url for this exact version, for ${platform}>`,
|
|
568
569
|
sha256: `<sha256 published with the ${platform} release>`,
|
|
569
570
|
});
|
|
@@ -165,16 +165,28 @@ by platform. Before that existed, the only way to keep a Linux binary off a lapt
|
|
|
165
165
|
|
|
166
166
|
Expected shape for most projects: a short `require` list, an empty or near-empty `install` list, and the provider CLI as the only thing always provisioned.
|
|
167
167
|
|
|
168
|
-
### The
|
|
168
|
+
### The four `install` methods
|
|
169
169
|
|
|
170
170
|
| `install` | Required fields | Use it when |
|
|
171
171
|
| --- | --- | --- |
|
|
172
172
|
| `release-zip` | `url` **and** `sha256` | The vendor publishes a Linux zip of the release. |
|
|
173
173
|
| `release-tar` | `url` **and** `sha256` — plus `binary` in practice | The vendor publishes no zip for Linux, only a `.tar.gz`. |
|
|
174
|
+
| `release-tree` | `url`, `sha256` **and** `binary` | The archive is a **directory**, not a single binary — an entry point that resolves its own siblings at run time. |
|
|
174
175
|
| `npm-global` | `package` | The tool ships on the npm registry. |
|
|
175
176
|
|
|
176
177
|
Anything else is rejected by name at plan time, so a typo fails loudly rather than silently installing nothing.
|
|
177
178
|
|
|
179
|
+
**`release-tree` exists because the single-file kinds fail silently on a tree.** They extract the archive and copy *one* file onto PATH, which is right for a static binary and wrong for anything that locates its own resources. Maestro is the case that forced it — one 314 MB zip containing:
|
|
180
|
+
|
|
181
|
+
```text
|
|
182
|
+
maestro/bin/maestro <- launcher
|
|
183
|
+
maestro/lib/*.jar <- 100+ MB of classpath
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
and a launcher that computes `CLASSPATH=$APP_HOME/lib/*` where `APP_HOME` is the parent of wherever the script itself sits. Declared as `release-zip` with `binary: maestro/bin/maestro`, the launcher lands in `~/.local/bin`, `APP_HOME` resolves to `~/.local`, and the classpath points at an empty directory. **The install reports success and the tool dies at first use** with `Could not find or load main class` — exactly the failure this manifest exists to turn into a loud setup error.
|
|
187
|
+
|
|
188
|
+
So `release-tree` extracts the whole archive to `~/.local/share/<name>/<version>` and puts a **wrapper** on PATH that `exec`s the entry point in place. Not a copy, and deliberately not a symlink either: a launcher that does not resolve symlinks before computing its own location would read the link's directory as its home and look for its resources beside the link — the same broken install, narrowed to a subset of tools. `binary` has no default here, because the archive root is a directory and guessing would install a directory as a binary.
|
|
189
|
+
|
|
178
190
|
Both archive kinds carry the **same** obligation and differ only in how they are unpacked: `url` and `sha256` are both mandatory, the checksum is verified *before* the archive is unpacked, and a version bump must move the checksum in the same reviewed commit. Neither is a weaker path than the other — `release-tar` exists because some tools worth pinning simply do not publish a zip. `gh` is the case that forced it: it ships `.deb`, `.rpm` and `.tar.gz` and nothing else, so a zip-only installer could not pin the CLI that Lisa's own commit guardrails shell out to.
|
|
179
191
|
|
|
180
192
|
**`binary` means something different for a tarball.** It defaults to the tool's `name` and is resolved relative to the unpacked directory. Release tarballs almost always nest their contents under a versioned top-level directory, so for `release-tar` it must be the path *within* the archive — `gh_2.83.0_linux_amd64/bin/gh`, not `gh`. A bare name there resolves to nothing after a download that otherwise succeeded, and the install fails at the copy step rather than at the fetch, which reads as a broken release when it is a manifest mistake. Bump the version and this path moves with it, alongside the `url` and the `sha256`.
|
|
@@ -212,6 +212,94 @@ function installReleaseTar(tool, binDir) {
|
|
|
212
212
|
}
|
|
213
213
|
}
|
|
214
214
|
|
|
215
|
+
/**
|
|
216
|
+
* Where a tree-shaped tool's extracted contents live.
|
|
217
|
+
*
|
|
218
|
+
* Versioned so a re-pin lands beside the old copy rather than on top of it, and
|
|
219
|
+
* outside `binDir` because only the entry point belongs on PATH.
|
|
220
|
+
* @param {object} tool Manifest entry.
|
|
221
|
+
* @param {string} binDir Directory holding the symlink.
|
|
222
|
+
* @returns {string} Absolute prefix for this tool and version.
|
|
223
|
+
*/
|
|
224
|
+
export function treePrefix(tool, binDir) {
|
|
225
|
+
return join(binDir, "..", "share", tool.name, String(tool.version));
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Install a pinned archive that is a DIRECTORY, not a single binary.
|
|
230
|
+
*
|
|
231
|
+
* `release-zip` and `release-tar` extract and then copy one file onto PATH,
|
|
232
|
+
* which is right for a static binary and silently wrong for anything that
|
|
233
|
+
* resolves its own siblings at run time. Maestro is the case that forced this:
|
|
234
|
+
*
|
|
235
|
+
* maestro/bin/maestro <- launcher
|
|
236
|
+
* maestro/lib/*.jar <- 100+ MB of classpath
|
|
237
|
+
*
|
|
238
|
+
* and the launcher computes `CLASSPATH=$APP_HOME/lib/*` where `APP_HOME` is the
|
|
239
|
+
* parent of wherever the script itself sits. Copy that launcher to
|
|
240
|
+
* `~/.local/bin` and APP_HOME becomes `~/.local`, so the classpath resolves to
|
|
241
|
+
* an empty directory. The install reports success and the tool fails at first
|
|
242
|
+
* use — the failure this manifest exists to turn into a loud setup error.
|
|
243
|
+
*
|
|
244
|
+
* So the whole tree is extracted and the entry point is SYMLINKED. A symlink,
|
|
245
|
+
* not a copy, precisely so that resolution walks back into the extracted tree.
|
|
246
|
+
* @param {object} tool Manifest entry.
|
|
247
|
+
* @param {string} binDir Directory to link the entry point into.
|
|
248
|
+
*/
|
|
249
|
+
function installReleaseTree(tool, binDir) {
|
|
250
|
+
const temporary = join(binDir, `.${tool.name}-download`);
|
|
251
|
+
const prefix = treePrefix(tool, binDir);
|
|
252
|
+
mkdirSync(temporary, { recursive: true });
|
|
253
|
+
try {
|
|
254
|
+
const archive = join(temporary, "download.archive");
|
|
255
|
+
execFileSync("curl", ["-fsSL", tool.url, "-o", archive], {
|
|
256
|
+
stdio: "inherit",
|
|
257
|
+
});
|
|
258
|
+
// Verify before unpacking, as everywhere else here: an unexpected archive
|
|
259
|
+
// must fail before any of its contents reach the filesystem.
|
|
260
|
+
verifyChecksum(archive, tool.sha256, tool.name);
|
|
261
|
+
|
|
262
|
+
// Replace rather than layer. Extracting over a previous version leaves both
|
|
263
|
+
// sets of jars on the classpath, which fails in a way that looks like a
|
|
264
|
+
// version bug rather than a stale install.
|
|
265
|
+
rmSync(prefix, { recursive: true, force: true });
|
|
266
|
+
mkdirSync(prefix, { recursive: true });
|
|
267
|
+
if (tool.url.endsWith(".zip")) {
|
|
268
|
+
execFileSync("unzip", ["-q", "-o", archive, "-d", prefix], {
|
|
269
|
+
stdio: "inherit",
|
|
270
|
+
});
|
|
271
|
+
} else {
|
|
272
|
+
execFileSync("tar", ["-xzf", archive, "-C", prefix], {
|
|
273
|
+
stdio: "inherit",
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
const entry = join(prefix, tool.binary);
|
|
278
|
+
if (!existsSync(entry)) {
|
|
279
|
+
throw new Error(
|
|
280
|
+
`${tool.name}: "binary" points at ${tool.binary}, which is not in the ` +
|
|
281
|
+
`archive.\nList the archive and use the path to the entry point ` +
|
|
282
|
+
`inside it, such as "maestro/bin/maestro".`
|
|
283
|
+
);
|
|
284
|
+
}
|
|
285
|
+
chmodSync(entry, 0o755);
|
|
286
|
+
|
|
287
|
+
// A WRAPPER, not a symlink. Both keep the tree intact, but a symlink only
|
|
288
|
+
// works for launchers that resolve symlinks before computing their own
|
|
289
|
+
// location — gradle's template does, and plenty of others do not. One that
|
|
290
|
+
// does not sees the link's directory as its home and looks for its
|
|
291
|
+
// classpath beside the link instead of beside itself, which is the same
|
|
292
|
+
// broken install this kind exists to prevent, reintroduced for a subset of
|
|
293
|
+
// tools. Exec'ing the absolute path removes the assumption entirely.
|
|
294
|
+
const shim = join(binDir, tool.name);
|
|
295
|
+
rmSync(shim, { force: true });
|
|
296
|
+
writeFileSync(shim, `#!/bin/sh\nexec ${JSON.stringify(entry)} "$@"\n`);
|
|
297
|
+
chmodSync(shim, 0o755);
|
|
298
|
+
} finally {
|
|
299
|
+
rmSync(temporary, { recursive: true, force: true });
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
215
303
|
/**
|
|
216
304
|
* Install a pinned global npm package.
|
|
217
305
|
* @param {object} tool Manifest entry.
|
|
@@ -239,6 +327,7 @@ export function installTool(tool, binDir) {
|
|
|
239
327
|
assertPinned(tool);
|
|
240
328
|
if (tool.install === "release-zip") installReleaseZip(tool, binDir);
|
|
241
329
|
else if (tool.install === "release-tar") installReleaseTar(tool, binDir);
|
|
330
|
+
else if (tool.install === "release-tree") installReleaseTree(tool, binDir);
|
|
242
331
|
else installNpmGlobal(tool);
|
|
243
332
|
}
|
|
244
333
|
|