wyvrnpm 2.10.2 → 2.12.2

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.
Files changed (49) hide show
  1. package/README.md +1914 -1860
  2. package/bin/{wyvrn.js → wyvrnpm.js} +66 -0
  3. package/cmake/cpp.cmake +9 -9
  4. package/cmake/functions.cmake +224 -224
  5. package/cmake/macros.cmake +284 -284
  6. package/package.json +3 -2
  7. package/src/auth.js +66 -66
  8. package/src/binary-dir.js +95 -0
  9. package/src/bootstrap/cookbook.js +196 -196
  10. package/src/bootstrap/detect.js +150 -150
  11. package/src/bootstrap/index.js +220 -220
  12. package/src/bootstrap/version.js +72 -72
  13. package/src/build/cache.js +344 -344
  14. package/src/build/clone.js +170 -170
  15. package/src/build/cmake.js +342 -342
  16. package/src/build/index.js +299 -297
  17. package/src/build/msvc-env.js +260 -260
  18. package/src/build/recipe.js +188 -188
  19. package/src/commands/add.js +141 -141
  20. package/src/commands/bootstrap.js +96 -96
  21. package/src/commands/build.js +482 -452
  22. package/src/commands/cache.js +189 -189
  23. package/src/commands/clean.js +80 -80
  24. package/src/commands/configure.js +92 -92
  25. package/src/commands/init.js +70 -70
  26. package/src/commands/install-skill.js +115 -115
  27. package/src/commands/install.js +730 -674
  28. package/src/commands/link.js +320 -320
  29. package/src/commands/profile.js +237 -237
  30. package/src/commands/publish.js +584 -555
  31. package/src/commands/show.js +252 -252
  32. package/src/commands/version.js +187 -0
  33. package/src/compat.js +273 -273
  34. package/src/conf/index.js +415 -391
  35. package/src/conf/namespaces.js +94 -94
  36. package/src/context.js +230 -230
  37. package/src/http-fetch.js +53 -53
  38. package/src/ignore.js +118 -118
  39. package/src/logger.js +122 -122
  40. package/src/options.js +303 -303
  41. package/src/settings-overrides.js +152 -152
  42. package/src/toolchain/deps.js +164 -164
  43. package/src/toolchain/index.js +212 -212
  44. package/src/toolchain/presets.js +356 -340
  45. package/src/toolchain/template.cmake +77 -77
  46. package/src/upload-built.js +265 -265
  47. package/src/version-range.js +301 -301
  48. package/src/zip-safe.js +52 -52
  49. package/src/zip-stream.js +126 -0
@@ -1,170 +1,170 @@
1
- 'use strict';
2
-
3
- const fs = require('fs');
4
- const path = require('path');
5
- const { spawn } = require('child_process');
6
-
7
- const log = require('../logger');
8
-
9
- /**
10
- * Spawn a command with inherited stdio, resolve on exit 0, reject otherwise.
11
- *
12
- * @param {string} cmd
13
- * @param {string[]} args
14
- * @param {{ cwd?: string }} [opts]
15
- * @returns {Promise<void>}
16
- */
17
- function run(cmd, args, opts = {}) {
18
- return new Promise((resolve, reject) => {
19
- const proc = spawn(cmd, args, { stdio: 'inherit', ...opts });
20
- proc.on('error', (err) => reject(new Error(
21
- `Failed to spawn ${cmd}: ${err.message} (is it installed and on PATH?)`,
22
- )));
23
- proc.on('close', (code) => {
24
- if (code === 0) resolve();
25
- else reject(new Error(`${cmd} ${args.join(' ')} exited ${code}`));
26
- });
27
- });
28
- }
29
-
30
- /**
31
- * Ensure `gitRepo` is cloned into `destDir` at commit `gitSha`.
32
- *
33
- * Semantics:
34
- * - If destDir does not exist → fresh clone + checkout gitSha.
35
- * - If destDir exists and the HEAD commit already matches gitSha → no-op.
36
- * - If destDir exists with a different HEAD → fetch + checkout the right
37
- * SHA, reusing already-downloaded git objects.
38
- * - If reuse fails for any reason (corrupted cache, unreachable SHA),
39
- * blow away the cache and fresh-clone.
40
- *
41
- * Each path tries a fast shallow fetch by SHA first, then falls back to a
42
- * full fetch. Some git servers disable `uploadpack.allowReachableSHA1InWant`
43
- * (notably older Bitbucket Server installs), which makes direct SHA fetches
44
- * fail with "upload-pack: not our ref"; the full-fetch fallback handles it.
45
- *
46
- * Credentials are delegated entirely to the user's ambient git config
47
- * (SSH keys, credential helpers). We do NOT manage auth.
48
- *
49
- * @param {{ gitRepo: string, gitSha: string, destDir: string }} args
50
- * @returns {Promise<void>}
51
- */
52
- async function cloneAtSha({ gitRepo, gitSha, destDir }) {
53
- if (!gitRepo) throw new Error('cloneAtSha: gitRepo is required');
54
- if (!gitSha) throw new Error('cloneAtSha: gitSha is required');
55
-
56
- // Reuse existing clone if possible.
57
- if (fs.existsSync(path.join(destDir, '.git'))) {
58
- try {
59
- await reuseExistingClone({ destDir, gitSha, gitRepo });
60
- return;
61
- } catch (err) {
62
- // An unreachable-commit error is fatal and won't be helped by rebuilding.
63
- if (/not reachable/.test(err.message)) throw err;
64
- log.warn(` cached clone unusable (${err.message}); rebuilding`);
65
- fs.rmSync(destDir, { recursive: true, force: true });
66
- }
67
- }
68
-
69
- await freshClone({ gitRepo, gitSha, destDir });
70
- }
71
-
72
- /**
73
- * Verify that `gitSha` is present and reachable in `destDir`. Throws with an
74
- * actionable error message when it isn't — the common root cause is an
75
- * unpushed publisher-side commit or a feature branch that was deleted after
76
- * publish, leaving the commit dangling on origin.
77
- */
78
- async function verifyShaPresent({ destDir, gitSha, gitRepo }) {
79
- try {
80
- await run('git', ['cat-file', '-e', `${gitSha}^{commit}`], { cwd: destDir });
81
- } catch {
82
- throw new Error(
83
- `commit ${gitSha.slice(0, 12)} is not reachable from any branch or tag on ${gitRepo}. ` +
84
- `Likely cause: the publisher's HEAD was not pushed, OR the commit was on a ` +
85
- `feature branch that was deleted/squash-merged after publish. ` +
86
- `Fix: the package maintainer should republish from a commit that is pushed ` +
87
- `and reachable from a remote branch or tag.`,
88
- );
89
- }
90
- }
91
-
92
- /**
93
- * Checkout `gitSha` in an existing clone. Tries shallow-SHA fetch first,
94
- * then full fetch (+ tags), then verifies reachability before checkout.
95
- */
96
- async function reuseExistingClone({ destDir, gitSha, gitRepo }) {
97
- const current = await getHeadSha(destDir);
98
- if (current === gitSha) return;
99
-
100
- log.info(` reusing existing clone, switching to ${gitSha.slice(0, 12)}`);
101
- try {
102
- // Fast path: shallow fetch the specific SHA directly.
103
- await run('git', ['fetch', '--depth', '1', 'origin', gitSha], { cwd: destDir });
104
- } catch {
105
- // Fallback: full fetch + tags. Fetching tags catches commits that live
106
- // only under `refs/tags/*` — e.g. a release commit whose branch was
107
- // deleted but whose tag remains.
108
- log.info(' shallow SHA fetch unsupported by server; fetching all refs + tags (slower)');
109
- await run('git', ['fetch', '--tags', 'origin'], { cwd: destDir });
110
- }
111
- await verifyShaPresent({ destDir, gitSha, gitRepo });
112
- await run('git', ['checkout', '--detach', gitSha], { cwd: destDir });
113
- }
114
-
115
- /**
116
- * Fresh clone. Tries `init + remote add + shallow-fetch <sha>` first, falls
117
- * back to a full `git clone --tags` if the server refuses direct-SHA
118
- * fetches. Verifies the commit is reachable before attempting checkout so
119
- * the failure mode is a clear error rather than a cryptic `unable to read
120
- * tree`.
121
- */
122
- async function freshClone({ gitRepo, gitSha, destDir }) {
123
- fs.mkdirSync(destDir, { recursive: true });
124
- log.info(` cloning ${gitRepo} at ${gitSha.slice(0, 12)} → ${destDir}`);
125
- try {
126
- await run('git', ['init', '--quiet'], { cwd: destDir });
127
- await run('git', ['remote', 'add', 'origin', gitRepo], { cwd: destDir });
128
- await run('git', ['fetch', '--depth', '1', 'origin', gitSha], { cwd: destDir });
129
- await verifyShaPresent({ destDir, gitSha, gitRepo });
130
- await run('git', ['checkout', '--detach', gitSha], { cwd: destDir });
131
- } catch (err) {
132
- // If the shallow-SHA fetch itself failed (server refuses it), fall
133
- // through to a full clone. If instead the SHA-reachability check failed,
134
- // re-throw with the actionable message — a full clone wouldn't help.
135
- if (/not reachable/.test(err.message)) throw err;
136
-
137
- log.warn(` shallow fetch by SHA failed (${err.message}); falling back to full clone`);
138
- fs.rmSync(destDir, { recursive: true, force: true });
139
- fs.mkdirSync(destDir, { recursive: true });
140
- // `--tags` brings down tag refs in the same round-trip so tag-only
141
- // commits are reachable too.
142
- await run('git', ['clone', '--quiet', '--tags', gitRepo, '.'], { cwd: destDir });
143
- await verifyShaPresent({ destDir, gitSha, gitRepo });
144
- await run('git', ['checkout', '--detach', gitSha], { cwd: destDir });
145
- }
146
- }
147
-
148
- /**
149
- * Return the current HEAD commit SHA of a git working tree, or null on error.
150
- * @param {string} dir
151
- * @returns {Promise<string|null>}
152
- */
153
- function getHeadSha(dir) {
154
- return new Promise((resolve) => {
155
- const proc = spawn('git', ['rev-parse', 'HEAD'], {
156
- cwd: dir,
157
- stdio: ['ignore', 'pipe', 'ignore'],
158
- });
159
- let out = '';
160
- proc.stdout.on('data', (c) => { out += c.toString(); });
161
- proc.on('error', () => resolve(null));
162
- proc.on('close', (code) => {
163
- if (code !== 0) return resolve(null);
164
- const sha = out.trim();
165
- resolve(/^[0-9a-f]{40}$/i.test(sha) ? sha : null);
166
- });
167
- });
168
- }
169
-
170
- module.exports = { cloneAtSha, getHeadSha };
1
+ 'use strict';
2
+
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+ const { spawn } = require('child_process');
6
+
7
+ const log = require('../logger');
8
+
9
+ /**
10
+ * Spawn a command with inherited stdio, resolve on exit 0, reject otherwise.
11
+ *
12
+ * @param {string} cmd
13
+ * @param {string[]} args
14
+ * @param {{ cwd?: string }} [opts]
15
+ * @returns {Promise<void>}
16
+ */
17
+ function run(cmd, args, opts = {}) {
18
+ return new Promise((resolve, reject) => {
19
+ const proc = spawn(cmd, args, { stdio: 'inherit', ...opts });
20
+ proc.on('error', (err) => reject(new Error(
21
+ `Failed to spawn ${cmd}: ${err.message} (is it installed and on PATH?)`,
22
+ )));
23
+ proc.on('close', (code) => {
24
+ if (code === 0) resolve();
25
+ else reject(new Error(`${cmd} ${args.join(' ')} exited ${code}`));
26
+ });
27
+ });
28
+ }
29
+
30
+ /**
31
+ * Ensure `gitRepo` is cloned into `destDir` at commit `gitSha`.
32
+ *
33
+ * Semantics:
34
+ * - If destDir does not exist → fresh clone + checkout gitSha.
35
+ * - If destDir exists and the HEAD commit already matches gitSha → no-op.
36
+ * - If destDir exists with a different HEAD → fetch + checkout the right
37
+ * SHA, reusing already-downloaded git objects.
38
+ * - If reuse fails for any reason (corrupted cache, unreachable SHA),
39
+ * blow away the cache and fresh-clone.
40
+ *
41
+ * Each path tries a fast shallow fetch by SHA first, then falls back to a
42
+ * full fetch. Some git servers disable `uploadpack.allowReachableSHA1InWant`
43
+ * (notably older Bitbucket Server installs), which makes direct SHA fetches
44
+ * fail with "upload-pack: not our ref"; the full-fetch fallback handles it.
45
+ *
46
+ * Credentials are delegated entirely to the user's ambient git config
47
+ * (SSH keys, credential helpers). We do NOT manage auth.
48
+ *
49
+ * @param {{ gitRepo: string, gitSha: string, destDir: string }} args
50
+ * @returns {Promise<void>}
51
+ */
52
+ async function cloneAtSha({ gitRepo, gitSha, destDir }) {
53
+ if (!gitRepo) throw new Error('cloneAtSha: gitRepo is required');
54
+ if (!gitSha) throw new Error('cloneAtSha: gitSha is required');
55
+
56
+ // Reuse existing clone if possible.
57
+ if (fs.existsSync(path.join(destDir, '.git'))) {
58
+ try {
59
+ await reuseExistingClone({ destDir, gitSha, gitRepo });
60
+ return;
61
+ } catch (err) {
62
+ // An unreachable-commit error is fatal and won't be helped by rebuilding.
63
+ if (/not reachable/.test(err.message)) throw err;
64
+ log.warn(` cached clone unusable (${err.message}); rebuilding`);
65
+ fs.rmSync(destDir, { recursive: true, force: true });
66
+ }
67
+ }
68
+
69
+ await freshClone({ gitRepo, gitSha, destDir });
70
+ }
71
+
72
+ /**
73
+ * Verify that `gitSha` is present and reachable in `destDir`. Throws with an
74
+ * actionable error message when it isn't — the common root cause is an
75
+ * unpushed publisher-side commit or a feature branch that was deleted after
76
+ * publish, leaving the commit dangling on origin.
77
+ */
78
+ async function verifyShaPresent({ destDir, gitSha, gitRepo }) {
79
+ try {
80
+ await run('git', ['cat-file', '-e', `${gitSha}^{commit}`], { cwd: destDir });
81
+ } catch {
82
+ throw new Error(
83
+ `commit ${gitSha.slice(0, 12)} is not reachable from any branch or tag on ${gitRepo}. ` +
84
+ `Likely cause: the publisher's HEAD was not pushed, OR the commit was on a ` +
85
+ `feature branch that was deleted/squash-merged after publish. ` +
86
+ `Fix: the package maintainer should republish from a commit that is pushed ` +
87
+ `and reachable from a remote branch or tag.`,
88
+ );
89
+ }
90
+ }
91
+
92
+ /**
93
+ * Checkout `gitSha` in an existing clone. Tries shallow-SHA fetch first,
94
+ * then full fetch (+ tags), then verifies reachability before checkout.
95
+ */
96
+ async function reuseExistingClone({ destDir, gitSha, gitRepo }) {
97
+ const current = await getHeadSha(destDir);
98
+ if (current === gitSha) return;
99
+
100
+ log.info(` reusing existing clone, switching to ${gitSha.slice(0, 12)}`);
101
+ try {
102
+ // Fast path: shallow fetch the specific SHA directly.
103
+ await run('git', ['fetch', '--depth', '1', 'origin', gitSha], { cwd: destDir });
104
+ } catch {
105
+ // Fallback: full fetch + tags. Fetching tags catches commits that live
106
+ // only under `refs/tags/*` — e.g. a release commit whose branch was
107
+ // deleted but whose tag remains.
108
+ log.info(' shallow SHA fetch unsupported by server; fetching all refs + tags (slower)');
109
+ await run('git', ['fetch', '--tags', 'origin'], { cwd: destDir });
110
+ }
111
+ await verifyShaPresent({ destDir, gitSha, gitRepo });
112
+ await run('git', ['checkout', '--detach', gitSha], { cwd: destDir });
113
+ }
114
+
115
+ /**
116
+ * Fresh clone. Tries `init + remote add + shallow-fetch <sha>` first, falls
117
+ * back to a full `git clone --tags` if the server refuses direct-SHA
118
+ * fetches. Verifies the commit is reachable before attempting checkout so
119
+ * the failure mode is a clear error rather than a cryptic `unable to read
120
+ * tree`.
121
+ */
122
+ async function freshClone({ gitRepo, gitSha, destDir }) {
123
+ fs.mkdirSync(destDir, { recursive: true });
124
+ log.info(` cloning ${gitRepo} at ${gitSha.slice(0, 12)} → ${destDir}`);
125
+ try {
126
+ await run('git', ['init', '--quiet'], { cwd: destDir });
127
+ await run('git', ['remote', 'add', 'origin', gitRepo], { cwd: destDir });
128
+ await run('git', ['fetch', '--depth', '1', 'origin', gitSha], { cwd: destDir });
129
+ await verifyShaPresent({ destDir, gitSha, gitRepo });
130
+ await run('git', ['checkout', '--detach', gitSha], { cwd: destDir });
131
+ } catch (err) {
132
+ // If the shallow-SHA fetch itself failed (server refuses it), fall
133
+ // through to a full clone. If instead the SHA-reachability check failed,
134
+ // re-throw with the actionable message — a full clone wouldn't help.
135
+ if (/not reachable/.test(err.message)) throw err;
136
+
137
+ log.warn(` shallow fetch by SHA failed (${err.message}); falling back to full clone`);
138
+ fs.rmSync(destDir, { recursive: true, force: true });
139
+ fs.mkdirSync(destDir, { recursive: true });
140
+ // `--tags` brings down tag refs in the same round-trip so tag-only
141
+ // commits are reachable too.
142
+ await run('git', ['clone', '--quiet', '--tags', gitRepo, '.'], { cwd: destDir });
143
+ await verifyShaPresent({ destDir, gitSha, gitRepo });
144
+ await run('git', ['checkout', '--detach', gitSha], { cwd: destDir });
145
+ }
146
+ }
147
+
148
+ /**
149
+ * Return the current HEAD commit SHA of a git working tree, or null on error.
150
+ * @param {string} dir
151
+ * @returns {Promise<string|null>}
152
+ */
153
+ function getHeadSha(dir) {
154
+ return new Promise((resolve) => {
155
+ const proc = spawn('git', ['rev-parse', 'HEAD'], {
156
+ cwd: dir,
157
+ stdio: ['ignore', 'pipe', 'ignore'],
158
+ });
159
+ let out = '';
160
+ proc.stdout.on('data', (c) => { out += c.toString(); });
161
+ proc.on('error', () => resolve(null));
162
+ proc.on('close', (code) => {
163
+ if (code !== 0) return resolve(null);
164
+ const sha = out.trim();
165
+ resolve(/^[0-9a-f]{40}$/i.test(sha) ? sha : null);
166
+ });
167
+ });
168
+ }
169
+
170
+ module.exports = { cloneAtSha, getHeadSha };