bvm-core 1.1.36 → 1.1.38
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/README.md +66 -2
- package/README.zh-CN.md +59 -2
- package/dist/bvm-shim.js +130 -45
- package/dist/bvm-shim.sh +24 -1
- package/dist/index.js +427 -158
- package/install.ps1 +70 -32
- package/install.sh +154 -65
- package/package.json +32 -19
- package/scripts/postinstall.js +185 -149
package/scripts/postinstall.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* BVM Post-install Script (Smart Edition)
|
|
5
|
-
*
|
|
5
|
+
* Bunker-First: Manages BVM private runtime in runtime/ bunker.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
const fs = require('fs');
|
|
@@ -22,7 +22,18 @@ function log(msg) { console.log(`[bvm] ${msg}`); }
|
|
|
22
22
|
function error(msg) { console.error(`\x1b[31m[bvm] ERROR: ${msg}\x1b[0m`); }
|
|
23
23
|
|
|
24
24
|
function run(cmd, args, opts = {}) {
|
|
25
|
-
|
|
25
|
+
const options = Object.assign({ encoding: 'utf-8' }, opts);
|
|
26
|
+
if (IS_WINDOWS) {
|
|
27
|
+
// Avoid shell: true to prevent DEP0190, but handle .cmd manually
|
|
28
|
+
if (cmd.endsWith('.cmd') || cmd.endsWith('.bat') || cmd === 'npm') {
|
|
29
|
+
// npm might be npm.cmd or npm.ps1, safest is cmd /c
|
|
30
|
+
return spawnSync('cmd', ['/d', '/s', '/c', cmd, ...args], { ...options, windowsVerbatimArguments: true });
|
|
31
|
+
}
|
|
32
|
+
// For executables like curl.exe, tar.exe, execute directly
|
|
33
|
+
return spawnSync(cmd, args, options);
|
|
34
|
+
}
|
|
35
|
+
// Unix: avoid shell: true for raw commands to prevent DEP0190
|
|
36
|
+
return spawnSync(cmd, args, options);
|
|
26
37
|
}
|
|
27
38
|
|
|
28
39
|
function findBinary(dir, name) {
|
|
@@ -40,45 +51,53 @@ function findBinary(dir, name) {
|
|
|
40
51
|
return null;
|
|
41
52
|
}
|
|
42
53
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
for (const registry of registries) {
|
|
53
|
-
log(`Checking ${pkgName} info from ${registry}...`);
|
|
54
|
-
const res = run('npm', ['info', pkgName, '--json', '--registry', registry]);
|
|
55
|
-
if (res.status === 0 && res.stdout) {
|
|
56
|
-
try {
|
|
57
|
-
const info = JSON.parse(res.stdout);
|
|
58
|
-
if (info.dist && info.dist.tarball) {
|
|
59
|
-
return { url: info.dist.tarball, version: info.version };
|
|
60
|
-
}
|
|
61
|
-
} catch (e) {}
|
|
62
|
-
}
|
|
54
|
+
function setupBunker(verDir, ver) {
|
|
55
|
+
const runtimeRoot = path.join(BVM_DIR, 'runtime');
|
|
56
|
+
if (!fs.existsSync(runtimeRoot)) fs.mkdirSync(runtimeRoot, { recursive: true });
|
|
57
|
+
|
|
58
|
+
const bunkerDir = path.join(runtimeRoot, ver);
|
|
59
|
+
if (verDir !== bunkerDir && fs.existsSync(verDir)) {
|
|
60
|
+
if (!fs.existsSync(bunkerDir)) fs.renameSync(verDir, bunkerDir);
|
|
61
|
+
} else if (!fs.existsSync(bunkerDir)) {
|
|
62
|
+
fs.mkdirSync(bunkerDir, { recursive: true });
|
|
63
63
|
}
|
|
64
|
-
return null;
|
|
65
|
-
}
|
|
66
64
|
|
|
67
|
-
|
|
68
|
-
const runtimeDir = path.join(BVM_DIR, 'runtime');
|
|
69
|
-
if (!fs.existsSync(runtimeDir)) fs.mkdirSync(runtimeDir, { recursive: true });
|
|
70
|
-
const currentLink = path.join(runtimeDir, 'current');
|
|
65
|
+
const currentLink = path.join(runtimeRoot, 'current');
|
|
71
66
|
const userCurrentLink = path.join(BVM_DIR, 'current');
|
|
67
|
+
const versionsDir = path.join(BVM_DIR, 'versions');
|
|
68
|
+
if (!fs.existsSync(versionsDir)) fs.mkdirSync(versionsDir, { recursive: true });
|
|
69
|
+
const versionLink = path.join(versionsDir, ver);
|
|
70
|
+
|
|
72
71
|
const linkType = IS_WINDOWS ? 'junction' : 'dir';
|
|
73
72
|
|
|
73
|
+
// 1. Link versions/vX.Y.Z -> runtime/vX.Y.Z (Crucial for bvm ls/use)
|
|
74
|
+
try { if (fs.existsSync(versionLink)) fs.unlinkSync(versionLink); } catch(e) {
|
|
75
|
+
if (IS_WINDOWS) run('cmd', ['/c', 'rmdir', versionLink]);
|
|
76
|
+
}
|
|
77
|
+
try { fs.symlinkSync(bunkerDir, versionLink, linkType); } catch(e) {}
|
|
78
|
+
|
|
79
|
+
// 2. Link current -> versions/vX.Y.Z
|
|
74
80
|
[currentLink, userCurrentLink].forEach(link => {
|
|
75
|
-
try { if (fs.existsSync(link)) fs.unlinkSync(link); } catch(e) {
|
|
76
|
-
|
|
81
|
+
try { if (fs.existsSync(link)) fs.unlinkSync(link); } catch(e) {
|
|
82
|
+
if (IS_WINDOWS) run('cmd', ['/c', 'rmdir', link]);
|
|
83
|
+
}
|
|
84
|
+
// Current always points to the registry entry
|
|
85
|
+
const target = link === currentLink ? bunkerDir : versionLink;
|
|
86
|
+
try { fs.symlinkSync(target, link, linkType); } catch(e) {}
|
|
77
87
|
});
|
|
78
88
|
|
|
79
89
|
const aliasDir = path.join(BVM_DIR, 'aliases');
|
|
80
90
|
if (!fs.existsSync(aliasDir)) fs.mkdirSync(aliasDir, { recursive: true });
|
|
81
91
|
fs.writeFileSync(path.join(aliasDir, 'default'), ver);
|
|
92
|
+
|
|
93
|
+
// 3. Generate bunfig.toml in bunker
|
|
94
|
+
const binDir = path.join(bunkerDir, 'bin');
|
|
95
|
+
const bunkerAbs = path.resolve(bunkerDir);
|
|
96
|
+
const binAbs = path.resolve(binDir);
|
|
97
|
+
const winBunker = bunkerAbs.replace(/\\/g, '\\\\');
|
|
98
|
+
const winBin = binAbs.replace(/\\/g, '\\\\');
|
|
99
|
+
const bunfigContent = `[install]\nglobalDir = "${winBunker}"\nglobalBinDir = "${winBin}"\n`;
|
|
100
|
+
fs.writeFileSync(path.join(bunkerDir, 'bunfig.toml'), bunfigContent);
|
|
82
101
|
}
|
|
83
102
|
|
|
84
103
|
function getNativeArch() {
|
|
@@ -86,9 +105,7 @@ function getNativeArch() {
|
|
|
86
105
|
if (process.platform === 'darwin' && arch === 'x64') {
|
|
87
106
|
try {
|
|
88
107
|
const check = spawnSync('sysctl', ['-n', 'sysctl.proc_translated'], { encoding: 'utf-8' });
|
|
89
|
-
if (check.stdout.trim() === '1')
|
|
90
|
-
return 'arm64';
|
|
91
|
-
}
|
|
108
|
+
if (check.stdout.trim() === '1') return 'arm64';
|
|
92
109
|
} catch (e) {}
|
|
93
110
|
}
|
|
94
111
|
return arch;
|
|
@@ -97,56 +114,79 @@ function getNativeArch() {
|
|
|
97
114
|
function hasAvx2() {
|
|
98
115
|
if (process.platform === 'win32') return true;
|
|
99
116
|
try {
|
|
100
|
-
if (process.platform === 'darwin') {
|
|
101
|
-
|
|
102
|
-
} else if (process.platform === 'linux') {
|
|
103
|
-
return fs.readFileSync('/proc/cpuinfo', 'utf-8').includes('avx2');
|
|
104
|
-
}
|
|
117
|
+
if (process.platform === 'darwin') return spawnSync('sysctl', ['-a'], { encoding: 'utf-8' }).stdout.includes('AVX2');
|
|
118
|
+
else if (process.platform === 'linux') return fs.readFileSync('/proc/cpuinfo', 'utf-8').includes('avx2');
|
|
105
119
|
} catch (e) {}
|
|
106
120
|
return true;
|
|
107
121
|
}
|
|
108
122
|
|
|
123
|
+
function getFastestRegistry() {
|
|
124
|
+
const registries = [
|
|
125
|
+
{ name: 'npmmirror', url: 'https://registry.npmmirror.com' },
|
|
126
|
+
{ name: 'npmjs', url: 'https://registry.npmjs.org' }
|
|
127
|
+
];
|
|
128
|
+
log('Racing registries for speed...');
|
|
129
|
+
const results = registries.map(reg => {
|
|
130
|
+
const start = Date.now();
|
|
131
|
+
const res = run('curl', ['-I', '-s', '--connect-timeout', '2', reg.url]);
|
|
132
|
+
return { ...reg, time: res.status === 0 ? (Date.now() - start) : 9999 };
|
|
133
|
+
});
|
|
134
|
+
results.sort((a, b) => a.time - b.time);
|
|
135
|
+
log(`Winner: ${results[0].name} (${results[0].time}ms)`);
|
|
136
|
+
return results;
|
|
137
|
+
}
|
|
138
|
+
|
|
109
139
|
function downloadAndInstall() {
|
|
110
140
|
const platform = process.platform === 'win32' ? 'windows' : process.platform;
|
|
111
|
-
const
|
|
112
|
-
const
|
|
113
|
-
const suffix = (arch === 'x64' && !hasAvx2()) ? '-baseline' : '';
|
|
114
|
-
const pkgName = `@oven/bun-${platform}-${arch}`;
|
|
141
|
+
const arch = getNativeArch() === 'arm64' ? 'aarch64' : 'x64';
|
|
142
|
+
const pkgName = `@oven/bun-${platform}-${arch}${ (arch === 'x64' && !hasAvx2()) ? '-baseline' : ''}`;
|
|
115
143
|
|
|
116
|
-
const
|
|
117
|
-
|
|
118
|
-
error(`Failed to locate ${pkgName} on both npmmirror and npmjs.`);
|
|
119
|
-
return false;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
const { url, version } = info;
|
|
123
|
-
const downloadUrl = url.replace('.tgz', `${suffix}.tgz`);
|
|
144
|
+
const sortedRegs = getFastestRegistry();
|
|
145
|
+
const versionsToTry = ['latest', '1.3.6'];
|
|
124
146
|
const tempTgz = path.join(os.tmpdir(), `bvm-bun-${Date.now()}.tgz`);
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
147
|
+
|
|
148
|
+
for (const verReq of versionsToTry) {
|
|
149
|
+
log(`\n--- Attempting Bun ${verReq} ---`);
|
|
150
|
+
for (const reg of sortedRegs) {
|
|
151
|
+
if (reg.time >= 9999) continue;
|
|
152
|
+
const target = verReq === 'latest' ? pkgName : `${pkgName}@${verReq}`;
|
|
153
|
+
log(`Checking ${target} from ${reg.name}...`);
|
|
154
|
+
const infoRes = run('npm', ['info', target, '--json', '--registry', reg.url]);
|
|
155
|
+
if (infoRes.status !== 0 || !infoRes.stdout) continue;
|
|
156
|
+
try {
|
|
157
|
+
const info = JSON.parse(infoRes.stdout);
|
|
158
|
+
const data = Array.isArray(info) ? info[0] : info;
|
|
159
|
+
if (!data.dist || !data.dist.tarball) continue;
|
|
160
|
+
const url = data.dist.tarball.trim();
|
|
161
|
+
const version = data.version;
|
|
162
|
+
log(`Downloading Bun v${version} from ${reg.name}...`);
|
|
163
|
+
// Use -C - to support resume, and increase timeout to 10 minutes (600s)
|
|
164
|
+
const dl = run('curl', ['-L', '--fail', '-C', '-', '--connect-timeout', '20', '--max-time', '600', '--retry', '3', '-o', tempTgz, url], { stdio: 'inherit' });
|
|
165
|
+
if (dl.status === 0) {
|
|
166
|
+
log('Extracting runtime... ');
|
|
167
|
+
const extractDir = path.join(os.tmpdir(), `bvm-ext-${Date.now()}`);
|
|
168
|
+
fs.mkdirSync(extractDir, { recursive: true });
|
|
169
|
+
const ex = run('tar', ['-xzf', tempTgz, '-C', extractDir]);
|
|
170
|
+
if (ex.status === 0) {
|
|
171
|
+
const foundBin = findBinary(extractDir, IS_WINDOWS ? 'bun.exe' : 'bun');
|
|
172
|
+
if (foundBin) {
|
|
173
|
+
const verName = 'v' + version.replace(/^v/, '');
|
|
174
|
+
const bunkerDir = path.join(BVM_DIR, 'runtime', verName);
|
|
175
|
+
const binDir = path.join(bunkerDir, 'bin');
|
|
176
|
+
if (!fs.existsSync(binDir)) fs.mkdirSync(binDir, { recursive: true });
|
|
177
|
+
fs.copyFileSync(foundBin, path.join(binDir, IS_WINDOWS ? 'bun.exe' : 'bun'));
|
|
178
|
+
setupBunker(bunkerDir, verName);
|
|
179
|
+
log(`🎉 Successfully installed Bun ${verName} via ${reg.name}.`);
|
|
180
|
+
try { fs.unlinkSync(tempTgz); } catch(e) {}
|
|
181
|
+
return true;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
} else {
|
|
185
|
+
// Cleanup partial file on complete failure of this URL attempt
|
|
186
|
+
try { if (fs.existsSync(tempTgz)) fs.unlinkSync(tempTgz); } catch(e) {}
|
|
187
|
+
}
|
|
188
|
+
} catch (e) {}
|
|
189
|
+
}
|
|
150
190
|
}
|
|
151
191
|
return false;
|
|
152
192
|
}
|
|
@@ -159,7 +199,6 @@ function createWrappers() {
|
|
|
159
199
|
const bunkerBun = path.join(BVM_DIR, 'runtime', 'current', 'bin', IS_WINDOWS ? 'bun.exe' : 'bun');
|
|
160
200
|
const bunkerBunWin = bunkerBun.replace(/\//g, '\\');
|
|
161
201
|
const bvmSrcWin = bvmSrc.replace(/\//g, '\\');
|
|
162
|
-
|
|
163
202
|
if (IS_WINDOWS) {
|
|
164
203
|
const content = `@echo off\r\nset "BVM_DIR=${bvmDirWin}"\r\nif exist "${bunkerBunWin}" (\r\n "${bunkerBunWin}" "${bvmSrcWin}" %*\r\n) else (\r\n node "${entryPath}" %*\r\n)`;
|
|
165
204
|
fs.writeFileSync(bvmBin, content);
|
|
@@ -173,92 +212,89 @@ function createWrappers() {
|
|
|
173
212
|
|
|
174
213
|
function main() {
|
|
175
214
|
log('Starting BVM post-install setup...');
|
|
215
|
+
if (!fs.existsSync(path.join(DIST_DIR, 'index.js'))) return;
|
|
216
|
+
[BVM_SRC_DIR, BVM_BIN_DIR].forEach(d => { if (!fs.existsSync(d)) fs.mkdirSync(d, { recursive: true }); });
|
|
176
217
|
|
|
177
|
-
//
|
|
178
|
-
if (
|
|
179
|
-
log('
|
|
180
|
-
|
|
181
|
-
|
|
218
|
+
// Windows-specific diagnostics
|
|
219
|
+
if (IS_WINDOWS) {
|
|
220
|
+
log('Windows detected. Checking PATH configuration...');
|
|
221
|
+
const userPath = process.env.PATH || '';
|
|
222
|
+
const bvmInPath = userPath.includes('.bvm\\shims') || userPath.includes('.bvm\\bin');
|
|
223
|
+
if (!bvmInPath) {
|
|
224
|
+
console.log('\x1b[33m[bvm] WARNING: BVM directories not found in PATH.\x1b[0m');
|
|
225
|
+
console.log('\x1b[33m[bvm] After installation, please run: bvm setup\x1b[0m');
|
|
226
|
+
}
|
|
182
227
|
}
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
{
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
const
|
|
192
|
-
if (
|
|
193
|
-
|
|
194
|
-
if (!a.dest.endsWith('.js')) fs.chmodSync(a.dest, 0o755);
|
|
228
|
+
const assets = [ { src: 'index.js', dest: path.join(BVM_SRC_DIR, 'index.js') }, { src: 'bvm-shim.sh', dest: path.join(BVM_BIN_DIR, 'bvm-shim.sh') }, { src: 'bvm-shim.js', dest: path.join(BVM_BIN_DIR, 'bvm-shim.js') } ];
|
|
229
|
+
assets.forEach(a => { const srcPath = path.join(DIST_DIR, a.src); if (fs.existsSync(srcPath)) fs.copyFileSync(srcPath, a.dest); });
|
|
230
|
+
|
|
231
|
+
function normalizeForCompare(p) {
|
|
232
|
+
try { return path.resolve(p).replace(/\\/g, '/').toLowerCase(); } catch { return String(p).replace(/\\/g, '/').toLowerCase(); }
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
function isLikelyScript(p) {
|
|
236
|
+
const lower = p.toLowerCase();
|
|
237
|
+
if (IS_WINDOWS) {
|
|
238
|
+
return lower.endsWith('.cmd') || lower.endsWith('.bat') || lower.endsWith('.ps1');
|
|
195
239
|
}
|
|
196
|
-
|
|
240
|
+
try {
|
|
241
|
+
const buf = fs.readFileSync(p, { encoding: 'utf-8' });
|
|
242
|
+
return buf.startsWith('#!');
|
|
243
|
+
} catch {
|
|
244
|
+
return false;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
197
247
|
|
|
198
248
|
let hasValidBun = false;
|
|
199
|
-
const
|
|
200
|
-
const checkBun = run(whichCmd, ['bun']);
|
|
201
|
-
|
|
249
|
+
const checkBun = run(IS_WINDOWS ? 'where' : 'which', ['bun']);
|
|
202
250
|
if (checkBun.status === 0 && checkBun.stdout) {
|
|
203
|
-
const
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
const verRes = run(binPath, ['--version']);
|
|
207
|
-
const ver = 'v' + (verRes.stdout || '1.3.6').trim().replace(/^v/, '');
|
|
208
|
-
const verDir = path.join(BVM_DIR, 'versions', ver);
|
|
209
|
-
|
|
210
|
-
// Architecture match check (Native vs. Emulated)
|
|
211
|
-
const sysArchRes = run(binPath, ['-e', 'console.log(process.arch)']);
|
|
212
|
-
const sysArch = (sysArchRes.stdout || '').trim();
|
|
213
|
-
const nativeArch = getNativeArch();
|
|
251
|
+
const candidates = checkBun.stdout.trim().split(/\r?\n/).map(p => p.trim()).filter(Boolean);
|
|
252
|
+
const bvmDirNorm = normalizeForCompare(BVM_DIR) + '/';
|
|
214
253
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
254
|
+
// Prefer a bun binary that is NOT under *this* BVM_DIR (fresh install),
|
|
255
|
+
// but allow other bun installs (including other .bvm locations) to bootstrap.
|
|
256
|
+
const binPath = candidates.find((p) => !normalizeForCompare(p).startsWith(bvmDirNorm)) || candidates[0];
|
|
257
|
+
if (binPath) {
|
|
258
|
+
log(`System Bun detected at: ${binPath}. Running Smoke Test...`);
|
|
259
|
+
const verRes = run(binPath, ['--version']);
|
|
260
|
+
const verRaw = (verRes.stdout || '').trim();
|
|
261
|
+
if (verRes.status === 0 && verRaw && !verRaw.includes('BVM Error') && /^\d+\.\d+\.\d+/.test(verRaw.replace(/^v/, ''))) {
|
|
262
|
+
const ver = 'v' + verRaw.replace(/^v/, '');
|
|
263
|
+
const bunkerDir = path.join(BVM_DIR, 'runtime', ver);
|
|
264
|
+
if (!fs.existsSync(path.join(bunkerDir, 'bin'))) {
|
|
265
|
+
fs.mkdirSync(path.join(bunkerDir, 'bin'), { recursive: true });
|
|
266
|
+
// Only copy real executables; avoid copying shims/scripts.
|
|
267
|
+
if (!isLikelyScript(binPath)) {
|
|
268
|
+
try { fs.copyFileSync(binPath, path.join(bunkerDir, 'bin', IS_WINDOWS ? 'bun.exe' : 'bun')); } catch (e) {}
|
|
226
269
|
}
|
|
227
|
-
} catch (e) {
|
|
228
|
-
error(`Failed to copy system Bun: ${e.message}`);
|
|
229
270
|
}
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
setupRuntimeLink(verDir, ver);
|
|
236
|
-
hasValidBun = true;
|
|
237
|
-
} else {
|
|
238
|
-
log('Smoke test failed. System Bun is incompatible with BVM core.');
|
|
271
|
+
const test = run(binPath, [path.join(BVM_SRC_DIR, 'index.js'), '--version'], { env: { BVM_DIR } });
|
|
272
|
+
if (test.status === 0) {
|
|
273
|
+
setupBunker(bunkerDir, ver);
|
|
274
|
+
hasValidBun = true;
|
|
275
|
+
}
|
|
239
276
|
}
|
|
240
277
|
}
|
|
241
278
|
}
|
|
242
|
-
|
|
243
|
-
if (!hasValidBun) {
|
|
244
|
-
log('No compatible system Bun found. Performing smart download...');
|
|
245
|
-
hasValidBun = downloadAndInstall();
|
|
246
|
-
}
|
|
247
|
-
|
|
279
|
+
if (!hasValidBun) hasValidBun = downloadAndInstall();
|
|
248
280
|
createWrappers();
|
|
249
|
-
const
|
|
250
|
-
const
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
process.exit(1);
|
|
255
|
-
}
|
|
281
|
+
const bvmEntry = path.join(BVM_BIN_DIR, IS_WINDOWS ? 'bvm.cmd' : 'bvm');
|
|
282
|
+
const baseEnv = Object.assign({}, process.env, { BVM_DIR, BVM_INSTALL_RUNNING: '1' });
|
|
283
|
+
run(bvmEntry, ['setup', '--silent'], { env: baseEnv });
|
|
284
|
+
// Ensure user shims are updated to the latest template logic (critical for Windows isolation).
|
|
285
|
+
run(bvmEntry, ['rehash', '--silent'], { env: baseEnv });
|
|
256
286
|
log('🎉 BVM initialized successfully.');
|
|
287
|
+
|
|
288
|
+
// Final Windows instructions
|
|
289
|
+
if (IS_WINDOWS) {
|
|
290
|
+
console.log('\n\x1b[36m[bvm] Next steps for Windows:\x1b[0m');
|
|
291
|
+
console.log(' 1. Close and reopen your terminal/PowerShell');
|
|
292
|
+
console.log(' 2. Run: bvm --version');
|
|
293
|
+
console.log(' 3. If command not found, run: bvm setup');
|
|
294
|
+
console.log(' 4. Add BVM to PATH manually if needed:');
|
|
295
|
+
console.log(` %USERPROFILE%\\.bvm\\shims`);
|
|
296
|
+
console.log(` %USERPROFILE%\\.bvm\\bin`);
|
|
297
|
+
}
|
|
257
298
|
}
|
|
258
299
|
|
|
259
|
-
try {
|
|
260
|
-
main();
|
|
261
|
-
} catch (e) {
|
|
262
|
-
error(e.message);
|
|
263
|
-
process.exit(1);
|
|
264
|
-
}
|
|
300
|
+
try { main(); } catch (e) { error(e.message); process.exit(1); }
|